coldfusion mx developer's cookbook (developer's library)

406

Upload: chris-reeves

Post on 27-Dec-2016

232 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: ColdFusion MX Developer's Cookbook (Developer's Library)
Page 2: ColdFusion MX Developer's Cookbook (Developer's Library)

ColdFusion® MXD E V E L O P E R ’ S C O O K B O O K

00 0672324628 FM 6/8/05 11:06 AM Page i

Page 3: ColdFusion MX Developer's Cookbook (Developer's Library)

00 0672324628 FM 6/8/05 11:06 AM Page ii

Page 4: ColdFusion MX Developer's Cookbook (Developer's Library)

Sams Publishing, 201 West 103rd Street, Indianapolis, Indiana 46290

DEVELOPER’S LIBRARY

D E V E L O P E R ’ S C O O K B O O K

Pete FreitagBrad LeupenChris Reeves

ColdFusion® MX

00 0672324628 FM 6/8/05 11:06 AM Page iii

Page 5: ColdFusion MX Developer's Cookbook (Developer's Library)

ColdFusion® MX Developer’s CookbookCopyright © 2003 by Sams Publishing

All rights reserved. No part of this book shall be reproduced, storedin a retrieval system, or transmitted by any means, electronic,mechanical, photocopying, recording, or otherwise, without writtenpermission from the publisher. No patent liability is assumed withrespect to the use of the information contained herein.Althoughevery precaution has been taken in the preparation of this book, thepublisher and author assume no responsibility for errors or omis-sions. Nor is any liability assumed for damages resulting from the useof the information contained herein.

International Standard Book Number: 0-672-32462-8

Library of Congress Catalog Card Number: 2002110482

Printed in the United States of America

First Printing:April 2003

04 03 02 01 4 3 2 1

TrademarksAll terms mentioned in this book that are known to be trademarksor service marks have been appropriately capitalized. SamsPublishing cannot attest to the accuracy of this information. Use of aterm in this book should not be regarded as affecting the validity ofany trademark or service mark.

Warning and DisclaimerEvery effort has been made to make this book as complete and asaccurate as possible, but no warranty or fitness is implied.The infor-mation provided is on an “as is” basis.The author and the publishershall have neither liability nor responsibility to any person or entitywith respect to any loss or damages arising from the informationcontained in this book or from the use of the CD or programsaccompanying it.

Acquisitions EditorShelley Johnston

Development EditorDamon Jordan

Managing EditorCharlotte Clapp

Project EditorAndy Beaster

Copy EditorKezia Endsley

IndexerErika Millen

ProofreaderSuzanne Thomas

Technical EditorsPeter ReeseChris Hiester

Team CoordinatorVanessa Evans

Media DeveloperDan Scherf

DesignerGary Adair

00 0672324628 FM 6/8/05 11:06 AM Page iv

Page 6: ColdFusion MX Developer's Cookbook (Developer's Library)

To my family, friends, and teachers:Thanks for everything.

—Pete Freitag

To my family and loved ones:Thank you so much for youron-going support.

—Brad Leupen

To my family and friends:Thanks for your support.

—Chris Reeves

00 0672324628 FM 6/8/05 11:06 AM Page v

Page 7: ColdFusion MX Developer's Cookbook (Developer's Library)

Contents at a GlanceIntroduction 1

I Datatypes and Containers

1 String Manipulation 7

2 Working with Lists 23

3 Arrays 37

4 Structures 51

5 Queries 67

6 Dates and Times 79

II Controlling Application Flow

7 Application Flow 91

8 Exception Handling 101

III Using Utility Tags

9 Charting Data 113

10 Files and Directories 125

11 Using Internet Protocols 137

12 Using Verity 151

13 User Authentication 159

00 0672324628 FM 6/8/05 11:06 AM Page vi

Page 8: ColdFusion MX Developer's Cookbook (Developer's Library)

IV Database Integration

14 Structured Query Language (SQL) 181

15 Stored Procedures 203

V Language Extensibility Features

16 User Defined Functions 217

17 ColdFusion Custom Tags 229

18 CFX API Custom Tags 239

19 Components 259

20 Objects 271

21 WDDX 281

22 XML 295

23 Web Services 305

24 J2EE Interoperability 317

VI Appendixes

A Online ColdFusion Resources 329

B Security 333

C Migrating from ColdFusion 5 to CFMX 339

D Converting Between Tags and Scripting 341

Index 349

00 0672324628 FM 6/8/05 11:06 AM Page vii

Page 9: ColdFusion MX Developer's Cookbook (Developer's Library)

viii Contents

Table of Contents

Table of Contents

Introduction 1How This Book Is Organized 1How to Use This Book 1

Chapter Overviews 2

I Datatypes and Containers

1 String Manipulation 71.0. Introduction 71.1. Concatenating Strings 71.2. Delimiting Strings 81.3. Using ASCII Character Codes 91.4. Forming Substring 101.5. Encrypting Strings 121.6. Hashing Strings 131.7. Iterating Through a String 141.8. Reading a File Line by Line 151.9. Searching a String 161.10. Replacing Substrings within a String 171.11. Using REFind() to Perform a Literal String

Search 181.12. Using Qualifiers to Indicate Multiplicity 191.13. Using Wildcards 201.14. Using Brackets 201.15. Performing OR Operations 211.16. Escaping Special Characters 211.17. Using Character Classes 22

00 0672324628 FM 6/8/05 11:06 AM Page viii

Page 10: ColdFusion MX Developer's Cookbook (Developer's Library)

ixContents

2 Working with Lists 232.0. Introduction 232.1. Creating Lists 232.2. Changing Delimiters 242.3. Extracting Elements 252.4. Handling Empty Values 262.5. Changing Values in a List 282.6. Searching a List 292.7. Sorting a List 302.8. Adding Qualifiers to a List 302.9. Looping Through a List 312.10. Looping Over a Structure’s Key List 322.11. Looping Until a List Is Empty 332.12. Parsing Input Forms 34

3 Arrays 373.0. Introduction 373.1. Creating an Array 373.2. Adding an Element to an Array 383.3. Displaying a Value in an Array 393.4. Looping over an Array 403.5. Manipulating Array Values 413.6. Sorting an Array 413.7. Multidimensional Arrays 443.8. Creating Arrays with More Than Three

Dimensions 453.9. Array Aggregate Functions 463.10. Array Utility Functions 473.11. Array Information Functions 48

4 Structures 514.0. Introduction 514.1. Creating a Structure 524.2. Using Structure Information Functions 524.3. Using Structure Management Functions 53

00 0672324628 FM 6/8/05 11:06 AM Page ix

Page 11: ColdFusion MX Developer's Cookbook (Developer's Library)

x Contents

4.4. Inserting Values into a Structure 554.5. Updating Values in a Structure 564.6. Displaying the Value of an Element in a

Structure Using the Key Name 574.7. Using Dot Notation 584.8. Looping Over a Structure 594.9. Using Structure Utility Functions 604.10. Copying Structures 614.11. Sorting Structures 63

5 Queries 675.0. Introduction 675.1. Querying a Database 675.2. Programmatically Creating Queries 695.3. Displaying Query Results 705.4. Using Query Variables 715.5. Creating Queries of Queries 735.6. Converting a Query Column to a List 755.7. Caching a Query 76

6 Dates and Times 796.0. Introduction 796.1. Creating a Date,Time, or

DateTime Object 796.2. Formatting Dates 806.3. Comparing Dates 826.4. Determining Date Differences 836.5. Formatting Times 846.6. Defining Time Spans 856.7. Using Date Information Functions 866.8. Managing Dates and Times in

Different Locales 88

00 0672324628 FM 6/8/05 11:06 AM Page x

Page 12: ColdFusion MX Developer's Cookbook (Developer's Library)

xiContents

II Controlling Application Flow

7 Application Flow 917.0. Introduction 917.1. Creating a ColdFusion Application 917.2. Using the Application Variable Scope 947.3. Implementing Session Management 957.4. Implementing Client Management 967.5. Storing Client State Using the Registry 977.6. Storing Client State Using Cookies 987.7. Storing Client State Using a Database 99

8 Exception Handling 1018.0. Introduction 1018.1. Catching Exceptions 1038.2. Catching Multiple Exceptions 1048.3. Examining an Exception 1058.4. Throwing Exceptions 1078.5. Re-Throwing Exceptions 108

III Using Utility Tags

9 Charting Data 1139.0. Introduction 1139.1. Creating a Simple Chart 1139.2. Managing the Chart Container 1149.3. Managing Chart Series 1179.4. Populating a Chart Series with Explicit

Values 1219.5. Populating Charts with Query Values 1219.6. Implementing Click-Through Behaviors in

Charts 1229.7. Administering Charts Through the ColdFusion

Administrator 123

00 0672324628 FM 6/8/05 11:06 AM Page xi

Page 13: ColdFusion MX Developer's Cookbook (Developer's Library)

xii Contents

10 Files and Directories 12510.0. Introduction 12510.1. Reading Files 12510.2. Writing Files 12610.3. Appending to Files 12710.4. Uploading Files 12910.5. Manipulating Files 13210.6. Listing Directories 13410.7. Manipulating Directories 136

11 Using Internet Protocols 13711.0. Introduction 13711.1. HTTP Requests 13711.2. Sending Email 14011.3. Receiving Email 14011.4. Querying an LDAP Directory 14111.5. Adding an LDAP Entry 14311.6. Updating an LDAP Entry 14411.7. Adding and Deleting an LDAP Entry’s

Attributes 14511.8. Renaming an Entry 14611.9. Deleting an LDAP Entry 14711.10. Sending a File via FTP 14711.11. Getting a File via FTP 148

12 Using Verity 15112.0. Introduction 15112.1. Creating a Collection 15112.2. Adding Information to a Verity Collection 15212.3. Searching a Verity Collection with Simple

Search 15512.4. Searching a Verity Collection with Explicit

Search 157

00 0672324628 FM 6/8/05 11:06 AM Page xii

Page 14: ColdFusion MX Developer's Cookbook (Developer's Library)

xiiiContents

13 User Authentication and Authorization 15913.0. Introduction 15913.1. Logging in a User 16013.2. Logging out a User 16013.3. Authenticating a User 16113.4. Obtaining the Logged-in User ID 16213.5. Authorizing a Block of Code 16213.6. Authorizing a Function 16413.7. Authentication Example 165

IV Database Integration

14 Structured Query Language (SQL) 18114.0. Introduction 18114.1 Inserting Data 18314.2. Updating Data 18314.3. Deleting Data 18414.4. Selecting Data 18514.5. Limiting Rows Returned 18514.6 Specifying Multiple Conditions 18614.7. Sorting Results 18714.8 Using Aliases 18714.9. Selecting from Multiple Tables 18814.10. Joining Two Tables 18914.11. Joining Three Tables 18914.12. Grouping Data with CFOUTPUT 19014.13. Performing Outer Joins 19114.14. Selecting Unique Values 19214.15. Using Aggregate Functions 19214.16. Grouping Aggregate Data 19314.17. Limiting Aggregate Results 19414.18. Using the IN Keyword 19414.19. Using IN with Web Forms 195

00 0672324628 FM 6/8/05 11:06 AM Page xiii

Page 15: ColdFusion MX Developer's Cookbook (Developer's Library)

xiv Contents

14.20. Matching a Wildcard Pattern 19614.21. Matching a Single Character 19714.22. Matching a Group of Characters 19814.23. Matching a Range of Characters 19814.24. Excluding a Group of Characters 19914.25. Excluding a Range of Characters 19914.26. Using Prepared Statements 200

15 Stored Procedures 20315.0. Introduction 20315.1. Writing a Simple Stored Procedure in

Microsoft SQL Server 20415.2. Writing a Simple Stored Procedure

in Oracle 20515.3. Invoking a Simple Stored Procedure 20615.4. Writing a Stored Procedure with Parameters

in Microsoft SQL Server 20715.5. Writing a Stored Procedure with Parameters

in Oracle 20815.6. Invoking a Stored Procedure with

Parameters 20915.7. Using Output Parameters 21115.8. Working with Multiple Result Sets 213

V Language Extensibility Features

16 User-Defined Functions 21716.0. Introduction 21716.1. Declaring a Function 21816.2. Function Arguments 22016.3. Returning Values 22216.4. Suppressing Output 22216.5. Recursive Functions 22316.6. Working with Function References 225

00 0672324628 FM 6/8/05 11:06 AM Page xiv

Page 16: ColdFusion MX Developer's Cookbook (Developer's Library)

xvContents

17 ColdFusion Custom Tags 22917.0. Introduction 22917.1. Creating a Simple Custom Tag 22917.2. Accessing a Custom Tag 23017.3. Using Attributes 23017.4. Returning a Result 23117.5. Adding Start and End Tags 23217.6. Building Nested Tags 23417.7. Encoding Custom Tags 23517.8. Using <cfmodule> 23617.9. Using <cfimport> 237

18 CFX API Custom Tags 23918.0. Introduction 23918.1. Creating a Simple Java CFX Tag 24018.2. Using Tag Attributes 24118.3. Setting ColdFusion Variables 24418.4. Using Queries in Java CFX Tags 24518.5. A Simple C++ CFX Tag 24718.6. Using Tag Attributes 25018.7. Setting ColdFusion Variables 25118.8. Using Queries in C++ CFX Tags 25318.9. Installing a Java CFX Tag 25618.10. Installing a C++ CFX Tag 257

19 Components 25919.0. Introduction 25919.1. Defining a Component 25919.2. Instantiating a Component 26219.3. Invoking a Component Method 26319.4. Component Inheritance 26519.5. Accessing a Component 26719.6. Using Component Meta Data 268

00 0672324628 FM 6/8/05 11:06 AM Page xv

Page 17: ColdFusion MX Developer's Cookbook (Developer's Library)

xvi Contents

20 Objects 27120.0. Introduction 27120.1. Creating a Java Object Instance 27120.2. Invoking Methods on an Object 27320.3. Using Properties on an Object 27520.4. Working with Java Objects 27520.5. Working with COM Objects 27620.6. Working with CORBA Objects 277

21 WDDX 28121.0. Introduction 28121.1. CFML to WDDX 28121.2. CFML to JavaScript 28321.3. WDDX to CFML 28521.4. WDDX to JavaScript 28621.5. Syndicating Content with WDDX 28721.6. Converting a Java Object into WDDX 29021.7. Deserializing WDDX in Java 292

22 XML 29522.0. Introduction 29522.1. Creating an XML Object with the <cfxml> Tag

29522.2. Creating an XML Object with the XmlNew()

Function 29622.3. Creating an XML Object from Another XML

Object 29822.4. Parsing an XML Document 29922.5. Accessing Attributes 29922.6. Accessing Children 30022.7. Accessing Inner Text 300

Technique 300Comments 301

22.8. Searching XML with XPath 30122.9. XSL Transformations 302

00 0672324628 FM 6/8/05 11:06 AM Page xvi

Page 18: ColdFusion MX Developer's Cookbook (Developer's Library)

xviiContents

23 Web Services 30523.0. Introduction 30523.1. Invoking a Web Service with CFINVOKE 30623.2. Creating an Instance of a Web Service 30723.3. Writing a Web Service 30823.4. Using Properties 30923.5. Deploying a Web Service 31123.6. Invoking a Web Service with .NET 31223.7. Invoking a Web Service with Java 315

24 J2EE Interoperability 31724.0. Introduction 31724.1. Redirecting to a Servlet or JSP 31824.2. Including a Servlet or JSP 31824.3. Accessing ColdFusion Pages from Servlets and

JSPs 31924.4. Sharing Data Between ColdFusion and

Servlets/JSPs 32024.5. Accessing Enterprise Java Beans 322

VI Appendixes

A Online ColdFusion Resources 329ColdFusion Web Sites 329Java Web Sites 331XML Web Sites 331Other Useful Web Sites 332

B Security 333Session Hijacking 333URL Injection Hacking 334File Uploading 335Denial of Service Attacks 335Cross Site Scripting 336

00 0672324628 FM 6/8/05 11:06 AM Page xvii

Page 19: ColdFusion MX Developer's Cookbook (Developer's Library)

xviii Contents

Sandbox Security 337Security Resources 337

C Migrating from ColdFusion 5 to ColdFusion MX 339

ColdFusion Code Compatibility Analyzer 339ColdFusion Settings Migration Wizard 339Changes to CFML Tags and Functions 340Database Operations 340Localization 340References 340

D Converting Between Tags and Scripting 341

The <cfscript> Tag 341If-Then Statements 343Loops 343Switch Statements 345Exception Handling 346

Index 347

00 0672324628 FM 6/8/05 11:06 AM Page xviii

Page 20: ColdFusion MX Developer's Cookbook (Developer's Library)

About the AuthorsPete Freitag is the co-founder and Chief Technology Officer of CFDev, a companythat builds Web components for ColdFusion and other languages. He has several years ofexperience developing database-driven Web applications, integrating with legacy systems,and product development. He contributes to the ColdFusion,Web development, andsoftware development communities regularly, and holds a BS in Software Engineeringfrom Clarkson University.

Brad Leupen is the Chief Technology Officer for the software company Noverant. Heholds an AB in Computer Science from Harvard University, where he focused on oper-ating systems and distributed systems research. He won the Derek Bok Award forExcellence in Teaching as a Teaching Fellow for several university undergraduate classes.He has closely followed the development of key Web technologies and standards, includ-ing J2EE, .NET, and XML.

Chris Reeves is a software developer for Religent, Inc. in Raleigh, NC, where he assistsin development for the company’s remote systems management software suite. He gradu-ated with a BA in English from Appalachian State University.

00 0672324628 FM 6/8/05 11:06 AM Page xix

Page 21: ColdFusion MX Developer's Cookbook (Developer's Library)

AcknowledgmentsI would first like to thank my co-authors—Brad and Chris—for sharing in the joys andpains involved in putting this book together.They both exerted a great deal of energyand sacrificed lots of time for this project.

I also owe thanks to Sams Publishing for providing me with several great editors towork with. In addition I’d like to thank Bob Kern and TIPS Technical Publishing fortheir hard work.

I’d like to thank my co-workers at CFDev and ActivSoftware for giving me the flexi-bility I needed while working on this project.

I must also thank my brother Steve for introducing me to the industry and providingme with knowledge and resources.Additionally, Dr. Douglas MacIntosh shared much ofhis knowledge and wisdom with me.

Finally, I’d like to thank everyone involved in the ColdFusion community for provid-ing a synergistic environment for learning about ColdFusion.

—Pete Freitag

I would like to thank the folks at Sams Publishing for their hard work in this project. Iwould also like to thank Chris and Pete. It was a joy to work with you. Finally, I wouldlike to thank Bob Kern and the employees of TIPS Technical Publishing. None of thiscould have happened without you.

—Brad Leupen

Thanks to my co-authors Brad and Pete for their outstanding work.Thanks also toeveryone involved with this project at Sams Publishing as well as Bob Kern and thegood folks at TIPS Technical Publishing.

—Chris Reeves

00 0672324628 FM 6/8/05 11:06 AM Page xx

Page 22: ColdFusion MX Developer's Cookbook (Developer's Library)

We Want to Hear from You!As the reader of this book, you are our most important critic and commentator.We valueyour opinion and want to know what we’re doing right, what we could do better, whatareas you’d like to see us publish in, and any other words of wisdom you’re willing topass our way.

You can email or write me directly to let me know what you did or didn’t like aboutthis book—as well as what we can do to make our books stronger.

Please note that I cannot help you with technical problems related to the topic of this book, andthat due to the high volume of mail I receive, I might not be able to reply to every message.

When you write, please be sure to include this book’s title and author as well as yourname and phone or email address. I will carefully review your comments and share themwith the author and editors who worked on the book.Email: [email protected]: Mark Taber

Associate PublisherSams Publishing201 West 103rd StreetIndianapolis, IN 46290 USA

Reader ServicesFor more information about this book or others from Sams Publishing, visit our Web siteat www.samspublishing.com.Type the ISBN (excluding hyphens) or the title of the bookin the Search box to find the book you’re looking for.

00 0672324628 FM 6/8/05 11:06 AM Page xxi

Page 23: ColdFusion MX Developer's Cookbook (Developer's Library)

00 0672324628 FM 6/8/05 11:06 AM Page xxii

Page 24: ColdFusion MX Developer's Cookbook (Developer's Library)

Introduction

The ability to produce applications with relative ease, power, and speed spawned thepopularity of ColdFusion, and is the reason many people use the technology.This bookattempts to further strengthen these assets by opening your eyes to the power ofColdFusion, and at the same time accelerating the ease and speed at which you developColdFusion applications.This book is not meant to introduce you to ColdFusion, rather it is meant to enrichyour development experience with solutions to everyday problems.We wrote this bookfor developers already familiar with the basics of ColdFusion and programming. Severalbooks available today do a fine job of explaining what a conditional is, as well as how toset a variable.We felt no need to reinvent the wheel with this book; it seemed better tocomplement your current ColdFusion library with an arsenal of solutions to everydayproblems.

How This Book Is OrganizedThis book is organized in such a way that it should be useful to experienced ColdFusiondevelopers as well as beginners. Each chapter is broken into problem-oriented sections.The sections are then broken down further into two parts:“Technique” and“Comments.”The technique portion of each section asserts a one- or two-sentence solution to theproblem presented in the section, followed by a short code sample.The technique sec-tion aims to quickly provide a solution to the problem with as few words as possible.This approach is especially friendly to experienced developers looking to find a quicksolution to a particular problem. Novice developers may also find it helpful to see a solu-tion to the problem upfront.The comments part of each section serves to describe the problem and its solution indetail. In the comments sections, you will find an explanation of the code presented inthe technique, along with additional information pertaining to the tags or functions usedto solve the problem.Within the comments, developers will find tips, tricks, and pointersto additional information.

How to Use This BookThis book is not intended to be read sequentially or cover to cover. Rather, when aproblem arises, you should use the Table of Contents or Index to find the appropriaterecipe and apply it.

01 0672324628 Intro 6/8/05 11:06 AM Page 1

Page 25: ColdFusion MX Developer's Cookbook (Developer's Library)

2 Introduction

Although you wouldn’t start using a traditional cookbook if you didn’t first know howto use your oven, this cookbook also is not meant to be an introduction to core princi-ples. Several books are currently on the market that can help you get started withColdFusion.In addition to this book and other books, the ColdFusion documentation is also a goodsource of reference and explanations. If you chose to install it, the ColdFusion documen-tation can be found in the /cfdocs directory of your Web root. ColdFusion documen-tation can also be found at livedocs.macromedia.com, which augments the docu-mentation with comments posted by developers.The comments are often helpful toclarify the use of a particular function, or to verify documentation bugs.

Chapter OverviewsChapter 1,“String Manipulation,” includes several basic problems such as string concate-nation and substring formation.The chapter also covers more complex problems such asusing regular expressions.Chapter 2,“Working with Lists,” explains what lists are, how to create them, and how towork with them. Some of the problems solved include looping through a list, searching alist, and changing the list delimiter.Chapter 3,“Arrays,” handles the creation, manipulation, and iteration of the array datatype in ColdFusion.Chapter 4,“Structures,” covers the structure data type.The topics covered includenotation, sorting, populating, and copying structures.Chapter 5,“Queries,” shows you how to output the contents of a query object, how tocreate a query programmatically, and how to run queries of queries.Chapter 6,“Dates and Times,” covers date and time formatting, date math, and locales.Chapter 7,“Application Flow,” covers the <cfapplication> tag. It explains state man-agement with sessions, and discusses client variables.Chapter 8,“Exception Handling,” shows how to catch, throw, and re-throw exceptions.Chapter 9,“Charting Data,” explains how to create charts with the <cfchart> tag.Chapter 10,“Files and Directories,” shows how to create, manipulate, and read files anddirectories.Chapter 11,“Using Internet Protocols,” covers the HTTP, LDAP, FTP, and email (SMTP,POP) protocols, and how to use them with ColdFusion.Chapter 12,“Using Verity,” shows you how to create and search a verity collection.Chapter 13,“User Authentication and Authorization,” takes you through the problemsand solutions encountered when managing users in an application.Chapter 14,“Structured Query Language (SQL),” explains how to use many of the fea-tures in the SQL language to query databases.Chapter 15,“Stored Procedures,” shows you how to create stored procedures and invokethem in ColdFusion.Chapter 16,“User-Defined Functions,” details the procedures necessary to create yourown functions in ColdFusion.

01 0672324628 Intro 6/8/05 11:06 AM Page 2

Page 26: ColdFusion MX Developer's Cookbook (Developer's Library)

3Introduction

Chapter 17,“ColdFusion Custom Tags,” explains how to create your own tags inColdFusion.Chapter 18,“CFX API Custom Tags,” explains how to create your own tags inColdFusion using Java and C++.Chapter 19,“Components,” shows you how to create, instantiate, invoke, and accessColdFusion components or CFCs.Chapter 20,“Objects,” explains how to use Java, COM, and CORBA objects in yourColdFusion applications.Chapter 21,“WDDX,” describes how to use WDDX to serialize data in XML and passit between applications.Chapter 22,“XML,” shows you how to extract data from XML, and how to transformXML documents with XSL.Chapter 23,“Web Services,” explains how to invoke and create Web Services.Chapter 24,“J2EE Interoperability,” explains how to work with J2EE technologies suchas servlets, JSP, and EJB.Appendix A,“Online ColdFusion Resources,” lists and describes resources forColdFusion developers available online.Appendix B,“Security,” outlines some common security vulnerabilities, as well as possi-ble solutions.Appendix C,“Migrating from ColdFusion 5 to CFMX,” describes procedures you cantake to migrate your code to work optimally on CFMX.Appendix D,“Converting Between Tags and Scripting,” shows you how to write logicwith <cfscript> blocks instead of with tags.

01 0672324628 Intro 6/8/05 11:06 AM Page 3

Page 27: ColdFusion MX Developer's Cookbook (Developer's Library)

01 0672324628 Intro 6/8/05 11:06 AM Page 4

Page 28: ColdFusion MX Developer's Cookbook (Developer's Library)

IDatatypes and Containers

1 String Manipulation

2 Working with Lists

3 Arrays

4 Structures

5 Queries

6 Dates and Times

02 0672324628 Part 01 6/8/05 11:07 AM Page 5

Page 29: ColdFusion MX Developer's Cookbook (Developer's Library)

02 0672324628 Part 01 6/8/05 11:07 AM Page 6

Page 30: ColdFusion MX Developer's Cookbook (Developer's Library)

1String Manipulation

1.0. IntroductionNo programming concept in the history of modern computing has appeared as over-complicated as string manipulation. How many of you C programmers have secretlywondered why strings are so tough to use? malloc()? free()? strcat()? What? “Ijust want to combine two words!” you might say to yourself, although not loud enoughfor other programmers to overhear.

Strings in C are represented as discreet arrays of characters, or bytes. If the length ofyour string exceeds that of the array, watch out! CGI programs, in particular, bring outthe worst in C’s low-level string API. Debugging memory leaks in your string-handlingcode can be particularly frustrating when that is all your program does.

Fortunately, the ColdFusion Markup Language (CFML) makes working with strings alot easier. Strings are the default data type in CFML and the language offers a richlibrary of functions and operators specifically designed to play with strings.

This chapter will explore many of these APIs as it describes how to solve many typi-cal programming problems.The chapter will start slow but the examples will quicklymove into some more advanced techniques, such as regular expressions.

1.1. Concatenating StringsYou want to combine two strings.

TechniqueUse the & operator to combine two strings into one.

<cfset s1 = “Hello “>

<cfset s2 = “World!”>

<cfset s = s1 & s2>

<cfoutput>#s#</cfoutput>

03 0672324628 CH01 6/8/05 11:07 AM Page 7

Page 31: ColdFusion MX Developer's Cookbook (Developer's Library)

CommentsThe & operator combines the two strings, “Hello” and “World!”, to create a newstring, “Hello World!”.The new string is then output to the resulting Web page byusing the <cfoutput>…</cfoutput> tags. Notice that you don’t have to worryabout the length of the final string.The ColdFusion application environment handlesallocating the memory for you.

1.2. Delimiting StringsYou want to represent many text fields as a single string.

TechniqueYou can create a simple comma-delimited list in ColdFusion by combining the differentvariables and delimiters.

<cfset x = “a”>

<cfset y = “b”>

<cfset z = “#x#,#y#”>

CommentsIn this example, you have created a comma-delimited list by joining the x and y vari-ables.The comma-delimited string is stored in the variable z.

If you have ever written a program to import data into a database, you know the joysof working with delimited strings.As long as Microsoft Excel is around, CSV files maywell remain the data interchange format of choice.

In fact, delimited strings hold a place near to ColdFusion’s heart as well.The CFMLlanguage includes an entire list processing library geared toward splicing and dicingdelimited strings.You’ll learn about support for list processing library in great detail inChapter 2,“Working with Lists.” However, let’s take a moment to see just how to createa delimited string, or list.

The key to a delimited list is (surprise!) the delimiter.The list uses a common delim-iter (usually a comma or a tab character) to segregate a string into a series of substrings.Quite often, data files will include multiline delimited strings, where each line representsan individual data record and each delimited substring represents a unique field value.

8 Chapter 1 String Manipulation

03 0672324628 CH01 6/8/05 11:07 AM Page 8

Page 32: ColdFusion MX Developer's Cookbook (Developer's Library)

91.3. Using ASCII Character Codes

1.3. Using ASCII Character CodesYou want to specify ASCII characters by their numeric value.

TechniqueUse the Chr() function to display a characters by their ASCII character code.

<cfset string = “Copyright “&Chr(169)&” 2002”>

<cfoutput>#string#</cfoutput>

The Chr() function returns the character that corresponds to a given ASCII charactercode.The following example inserts the copyright symbol ([cr]) into a line of text byreferencing its ASCII character code.

The resulting Web page will faithfully render the string “Copyright [cr] 2002”just as the code implies.

This is particularly useful for embedding special characters (such as carriage returnsand line feeds) into strings. ColdFusion also provides the Asc() function, which returnsa character’s numeric value.

To display the alphabet, use the Asc() function to find the beginning of alphabet,and then loop to the end, displaying each character with the Chr() function.

<cfset start = Asc(‘A’)>

<cfset end = start + 25>

<cfloop from=”#start#” to=”#end#” index=”i”>

<cfset charUpper = Chr(i)>

<cfset charLower = Chr(i+32)>

<cfoutput>#charUpper# --> #charLower#<br></cfoutput>

</cfloop>

CommentsRather than type 52 letters into the source file, you can do this by taking advantage ofthe fact that alphabetic characters are represented by a contiguous numeric sequence inthe ASCII character set. (The observant reader may note that this algorithm requires 227characters.)

The first step is to obtain the beginning ASCII number by using the Asc() functionto find the ASCII equivalent of the uppercase letter A.Adding 25 to this value will thenresult in the number of the letter Z.You then iterate over this range by using the<cfloop> tag. For each number in the range, you find the corresponding character byusing the Chr() function.You can discover the numeric code of the lowercase versionof the letter by adding an offset of 32.The fruits of your labor look something like this:

A --> a

B --> b

. . .

Z --> z

03 0672324628 CH01 6/8/05 11:07 AM Page 9

Page 33: ColdFusion MX Developer's Cookbook (Developer's Library)

10 Chapter 1 String Manipulation

1.4. Forming SubstringYou want to divide a string into smaller substrings.

TechniqueUse the Right() and Left() functions to form substrings.

<cfparam name=”str” default=”The quick brown fox jumped over the lazy dog.”>

<cfparam name=”pivot” default=”1”>

<html>

<body>

<cfoutput>

<cfif isdefined(“submitted”)>

<cfset s1 = Left(str,pivot)>

<cfif Len(str) gt pivot>

<cfset s2 = Right(str,Len(str)-pivot)>

<cfelse>

<cfset s2 = “”>

</cfif>

<cfset str = s2&s1>

</cfif>

#str#

<form action=”substrings.cfm” method=”post”>

<select name=”pivot”>

<cfloop from=”1” to=”#Len(str)#” index=”i”>

<cfif i eq pivot>

<option value=”#i#” selected=”yes”>#i#</option>

<cfelse>

<option value=”#i#”>#i#</option>

</cfif>

</cfloop>

</select>

<input type=”hidden” name=”str” value=”#str#”>

<input type=”submit” name=”submitted” value=”Pivot String”>

</form>

</cfoutput>

</body>

</html>

CommentsThis example starts with the string “The quick brown fox jumped over thelazy dog.” It then asks the users to select a number between 1 and 45, which will beused as the pivot point in the string. Once the number is submitted, the ColdFusion

03 0672324628 CH01 6/8/05 11:07 AM Page 10

Page 34: ColdFusion MX Developer's Cookbook (Developer's Library)

111.4. Forming Substring

template creates two new strings.The first string is the result of performing a Left()function on the string to take the first n characters up to, and including, the pivot point.The second is the result of a Right() function, which takes all of the characters to theright of the pivot point. Finally, the page swaps the two substrings and displays the resultto the users.The new, rotated string is used as the starting point the next time the userssubmit the page.

ColdFusion MX includes a number of utility functions for dissecting, rearranging, andassembling strings.These functions are listed in Table 1.1.

Table 1.1 CFML Substring Functions

Find(substring, string [, start]) Finds the first occurrence of a substring withina string, beginning at an optional start posi-tion.The search is case-sensitive. Returns theposition of the substring within the string, or 0if the substring is not found.

FindNoCase(substring, string ) Same as Find() except that the [,start] search is not case-sensitive.

FindOneOf(set, string [, start]) Finds the first occurrence of any one of a listof characters within a string. Returns the posi-tion of the first character found in the string,or 0 if none of the characters appears in thestring.

Left(string, count) Returns a substring of specified length, startingat the beginning of the string.

Len(string) Returns the length, in characters, of the speci-fied string.

LTrim(string) Returns the specified string stripped of theleading spaces.

Mid(string, start, count) Returns a substring of length count begin-ning at position start in the specified string.

RemoveChars(string, start, count) Returns a copy of the string with count char-acters removed, beginning at position start.

Replace(string, substring1, ) Replaces one or more substring2 [, scope] occurrences of substring1 with substring2 in

string.The search is case-sensitive.

ReplaceNoCase(string, substring1, Replaces one or more occurrences of substring2 [, scope]) substring1 with substring2 in string.The search

is not case-sensitive.

Right(string, count) Returns count characters from the end of thestring.

RTrim(string) Returns the string with all trailing spacesremoved.

03 0672324628 CH01 6/8/05 11:07 AM Page 11

Page 35: ColdFusion MX Developer's Cookbook (Developer's Library)

12 Chapter 1 String Manipulation

StripCR(string) Returns the string with all return charactersremoved.

Trim(string) Returns the string with all leading and trailingspaces removed.

1.5. Encrypting StringsYou want to encrypt a string.

TechniqueUse the Encrypt() and Decrypt() functions to encrypt or decrypt strings.

<cfset theString = “ColdFusion”>

<!--- I also use “1234” for my luggage combination --->

<cfset key = “key”>

<cfset encryptedString = Encrypt(theString,key)>

<cfoutput>Encrypted String: “#encryptedString#”</cfoutput><br>

<cfset decryptedString = Decrypt(encryptedString,key)>

<cfoutput>Decrypted String: “#decryptedString#”</cfoutput>

CommentsYou might find it necessary to encrypt and decrypt strings for storage or for transmissionacross a network.The CFML language includes two functions to aid in this effort:Encrypt() and Decrypt().The encryption algorithm used by the functions is basedon a private key and the algorithm’s security is tied to the security of the key. Note thatthis approach differs in this way from the public-key encryption techniques used in thepopular RSA encryption algorithm.

The syntax for both of these functions is straightforward. Encrypt() takes twostrings as arguments: the string to be encrypted and a key to be used in the encryptionprocess.The function returns an encrypted string, which can be (and usually is) muchlonger than the original.The Decrypt() function also takes two strings as arguments:the encrypted string to be decrypted and the key that was used to encrypt the originalstring.The function reverses the encryption algorithm and returns the original string as aresult. Note the importance of using the same key when calling the Encrypt() andDecrypt() functions. Be sure not to expose this key to outsiders, as malicious users canthen thwart your security efforts!

The result of executing this page looks like this:

Table 1.1 Continued

03 0672324628 CH01 6/8/05 11:07 AM Page 12

Page 36: ColdFusion MX Developer's Cookbook (Developer's Library)

131.6. Hashing Strings

Encrypted String: “*>H1W%R&X0-Q”UP ”

Decrypted String: “ColdFusion”

Although the Encrypt() and Decrypt() functions are technically secure in and ofthemselves, limitations in private key security can make them undesirable for use in e-commerce applications.The sender and receiver must agree on a common key before amessage can be encrypted.The sharing of this key is often insecure, thereby compromis-ing the security of the entire transaction.

However, ColdFusion string encryption is perfectly fine for protecting simple dataelements. It is more than suitable for disguising, say, system variables in a page’s URL.Usethe Encrypt() and Decrypt() functions to encrypt or decrypt strings.

1.6. Hashing StringsYou want to hash, or forward-encrypt, a string for comparison purposes.

TechniqueUse the Hash() function to encode a string.

<html>

<body>

<cfif isdefined(“submitted”)>

<cfset orig_password = “password”>

<cfset hashedPw = Hash(orig_password)>

<cfset hashedAttempt = Hash(password)>

<cfif hashedPw is hashedAttempt>

You entered the correct password.

<cfelse>

Password attempt failed. Please try again.

</cfif>

</cfif>

<form action=”hash.cfm” method=”post”>

Enter your password: <input type=”password” name=”password”><br>

<input type=”hidden” name=”submitted” value=”true”>

<input type=”submit”>

</form>

</body>

</html>

CommentsIn addition to the Encrypt() and Decrypt() functions, ColdFusion MX provides aforward-encryption function called Hash(). Hash() uses the MD5 algorithm toencrypt a string.The Hash() function is useful for tasks such as storing a password

03 0672324628 CH01 6/8/05 11:07 AM Page 13

Page 37: ColdFusion MX Developer's Cookbook (Developer's Library)

14 Chapter 1 String Manipulation

securely and comparing user-supplied passwords against the stored copy.The one-sidednature of the Hash() function means that the original password cannot be directlyreproduced with a copy of the hashed password.The only way somebody can crack it isto test the Hash() function on every possible password string.

The previous example illustrates the use of the Hash() function to forward-encryptand compare a user-supplied password with the original.This program returns successonly if the user enters the string “password”.

1.7. Iterating Through a StringYou want to loop over each substring in a single string.

TechniqueUse the <cfloop> tag and the Mid() function to iterate over a string.

<html>

<body>

<cfif isdefined(“submitted”)>

<cfset newstring = “”>

<cfloop from=”1” to=”#Len(text)#” index=”i”>

<cfset chr = Mid(text,i,1)>

<cfset newstring = chr&newstring>

</cfloop>

<cfoutput>#newstring#</cfoutput><br>

</cfif>

<form action=”reverse.cfm” method=”post”>

Enter text to be reversed:<br>

<textarea name=”text”></textarea>

<input type=”hidden” name=”submitted” value=”true”>

<input type=”submit”>

</form>

</body>

</html>

CommentsCFML allows you to inspect individual characters within a string. For example, let’s saythat your boss has asked you to write a Web page that reverses a user-defined string.Thefirst question you need to ask yourself is:“Why am I working here?”The second ques-tion should be:“How can I use CFML to do this?”

The reversal algorithm is simple: you loop from 1 to the string’s length and use theMid() function (which you learned about earlier) to extract the character at each posi-tion in the string.The character is prepended to a resulting string, which you show tothe users (and your boss) when you are finished.

03 0672324628 CH01 6/8/05 11:07 AM Page 14

Page 38: ColdFusion MX Developer's Cookbook (Developer's Library)

151.8. Reading a File Line by Line

Lazy programmers would take the easy way out and use the CFML functionReverse() to do this.

1.8. Reading a File Line by LineYou want to parse an input file into separate lines of data.

TechniqueUse <cffile> and <cfloop> to iterate over a file, line by line.

<cfset filename = GetDirectoryFromPath(GetCurrentTemplatePath())&”data.txt”>

<cffile action=”read” file=”#filename#” variable=”data”>

<cfloop list=”#data#” index=”line” delimiters=”#chr(10)##chr(13)#”>

<cfoutput>#line#<p></cfoutput>

</cfloop>

CommentsThis example reads a small text file and parses it into multiple lines of data.The trick tothis is to treat the entire file as a delimited text string and use the <cfloop> tag to iter-ate over a list of lines.You can use the carriage-return and line-feed characters as thedelimiters in your string.

The first two lines of the template read a file called data.txt (see Chapter 10,“Filesand Directories,” for more information on file I/O). <cffile> expects the filenameargument to be an absolute path name, so you might want to use theGetCurrentTemplatePath() function to handle relative paths.

The last three lines form the heart of this little program.These lines call the<cfloop> tag, specifying the list attribute.This type of loop will iterate over a delim-ited string. In this case, the string contains the data file.This example uses the string“#chr(10)##chr(13)#” (line feed and carriage return) as the delimiter (UNIX usersmay just require “#chr(10)#”).This technique will cause the loop to iterate over eachline in the file, assigning the contents of the line to the variable line in the program. Itthen prints the line and continues.

One of the reasons that ColdFusion has been so popular for so long is its vast libraryof I/O tags and functions. ColdFusion is an excellent platform for moving data from onedata repository to another. It is incredibly easy to access information in file systems, data-bases, FTP/HTTP sites, LDAP directories, mail servers, and so on.

03 0672324628 CH01 6/8/05 11:07 AM Page 15

Page 39: ColdFusion MX Developer's Cookbook (Developer's Library)

16 Chapter 1 String Manipulation

1.9. Searching a StringYou want to search a string for occurrences of a specific substring.

TechniqueUse the Find() and FindNoCase() functions to search a string.

<cfparam name=”searchstring” default=””>

<html>

<body>

<cfif isdefined(“submitted”)>

<!--- read the file --->

<cfset filename = GetDirectoryFromPath(

GetCurrentTemplatePath())&”TMch04.txt”>

<cffile action=”read” file=”#filename#” variable=”data”>

<cfset cnt = 0>

<cfset pos = 0>

<cfset search = true>

<cfloop condition = “search is true”>

<cfif isdefined(“casesensitive”) and casesensitive is 1>

<cfset pos = Find(searchstring,data,pos+1)>

<cfelse>

<cfset pos = FindNoCase(searchstring,data,pos+1)>

</cfif>

<cfif pos gt 0>

<cfset cnt = cnt + 1>

<cfelse>

<cfset search = false>

</cfif>

</cfloop>

<cfoutput>The string <b>#searchstring#</b>

appeared #cnt# time(s).<p></cfoutput>

</cfif>

<form action=”search.cfm” method=”post”>

<cfoutput>Enter a string to search for:

<input type=”text” name=”searchstring” value=”#searchstring#”>

<br></cfoutput>

Case sensitive?

<cfif isdefined(“casesensitive”) and casesensitive is 1>

<input type=”checkbox” name=”casesensitive” value=”1” checked=”yes”>

<cfelse>

<input type=”checkbox” name=”casesensitive” value=”1”>

</cfif>

03 0672324628 CH01 6/8/05 11:07 AM Page 16

Page 40: ColdFusion MX Developer's Cookbook (Developer's Library)

171.10. Replacing Substrings within a String

<input type=”hidden” name=”submitted” value=”true”>

<input type=”submit”>

</form>

</body>

</html>

CommentsColdFusion includes a nice string-searching utility that allows you to test for certainsubstrings within a larger string.These searches can be case-sensitive or case-insensitive,depending on your mood.You should familiarize yourself with two functions: Find()and FindNoCase().They will come in handy at some time or another, so you might aswell learn them now.

In the following example, you create a small application that enables you to search forstrings in Chapter 4 of Alexandre Dumas’ The Three Musketeers, in which the hero,d’Artagnan, meets the Royal Musketeers—Athos, Porthos, and Aramis—for the firsttime.

This example prompts the users to enter a search string. It will then load the chapter’stext into memory and count the number of times the search string appears.In order to count each occurrence of the string, you must make use of the optionalstart parameter for the Find() and FindNoCase() functions.The idea is to call theFind() function repeatedly, passing the result of the preceding function call (the startingposition of the substring) as the new search starting position. In other words, makeFind() resume the search where it stopped before. Be sure to avoid an infinite loop byadding “1” to the start position each time through!

1.10. Replacing Substrings within a StringYou want to replace instances of a substring with another substring.

TechniqueUse the Replace() and ReplaceNoCase() functions to replace a substring withanother string.

<cfparam name=”str” default=”Peter Piper picked a peck of pickled peppers.

A peck of pickled peppers Peter Piper picked.

If Peter Piper picked a peck of pickled peppers,

where’s the peck of pickled peppers Peter Piper picked?”>

<cfparam name=”substring1” default=””>

<cfparam name=”substring2” default=””>

<html>

03 0672324628 CH01 6/8/05 11:07 AM Page 17

Page 41: ColdFusion MX Developer's Cookbook (Developer's Library)

18 Chapter 1 String Manipulation

<body>

<cfoutput>

<cfif isdefined(“submitted”)>

<cfset str = ReplaceNoCase(str,substring1,substring2,”all”)>

</cfif>

#str#

<form action=”replace.cfm” method=”post”>

Replace this string:

<input type=”text” name=”substring1”

value=”#substring1#”><br />

With this string:

<input type=”text” name=”substring2”

value=”#substring2#”><br />

<input type=”hidden” name=”str” value=”#str#”>

<input type=”submit” name=”submitted”>

</form>

</cfoutput>

</body>

</html>

CommentsThe Replace() and ReplaceNoCase() functions take as arguments a string to besearched, the substring to be replaced, the substring to do the replacing, and an optionalscope parameter.

The scope parameter dictates whether the function should replace all occurrences ofsubstring1 with substring2 (“all”) or just the first occurrence (“one”). Be care-ful—the default behavior of Replace() and ReplaceNoCase() is to replace just thefirst occurrence. Be sure to use the “all” scope option if you intend to perform aglobal search and replace.

The previous example attempts to make a popular tongue-twister more manageableby replacing “peppers” with some other vegetable.Use the Replace() and ReplaceNoCase() functions liberally to child-proof yourWeb bulletin board!

1.11. Using REFind() to Perform a LiteralString Search

You want to search for a substring within another string.

03 0672324628 CH01 6/8/05 11:07 AM Page 18

Page 42: ColdFusion MX Developer's Cookbook (Developer's Library)

TechniqueUse the REFind() function to perform a literal string search.

<cfset pos = REFind(“Sun”,”The Sun Also Rises”)>

CommentsThis will return the value 5, indicating the start position of the first occurrence of thesubstring “Sun” in the string “The Sun Also Rises”.

ColdFusion’s regular expression functionality lies within the functions REFind,REReplace, REReplaceNoCase, and REFindNoCase. In the case of literal text search-es, the functions operate just like their “sans-RE” counterparts.

1.12. Using Qualifiers to Indicate MultiplicityYou want to use the *, ?, and + symbols to specify a character’s multiplicity.

TechniqueUse the *, ?, and + quantifiers to indicate the multiplicity of the preceding character.

REReplace(“Please pahhk the cahhh in the Hahvahd Yahhhd”,“ah+”, “ar”, “all”)

CommentsThere are three common symbols used as quantifiers here: *, ?, and +.They are append-ed to a character (or a group of characters) to indicate how many times that charactershould appear in the search string.The * quantifier represents “zero or more.”The ?quantifier represents “zero or one.” Finally, the + character represents “one or more.” Let’slook at a few examples, the first of which I like to call the “Bostonian Translator.”

The previous example returns the correct spelling of the phrase “Park the carin the Harvard Yard”. How does this work? Is it because Allaire used to be head-quartered in Cambridge? Nope.This works because you tell it to.The example tellsColdFusion to look for an a followed by one or more hs and to replace them all withthe string “ar”.

What would happen if you used the * quantifier instead of +?

REReplace(“Please pahhk the cahhh in the Hahvahd Yahhhd”,”ah*”, “ar”, “all”)

This is no good. Instead of English, you get the phrase “Plearse park the car inthe Harvard Yard”. Plearse? The problem is that the regular expression parser didwhat you told it to do. It looked for an a followed by zero or more hs. It found the sin-gle a in “Please” and replaced it.

191.12. Using Qualifiers to Indicate Multiplicity

03 0672324628 CH01 6/8/05 11:07 AM Page 19

Page 43: ColdFusion MX Developer's Cookbook (Developer's Library)

1.13. Using WildcardsYou want to use the ., ^, and $ characters to represent other characters.

TechniqueUse the ., ^, and $ characters to represent other characters.

REReplace(“a man, a plan, a canal, panama!”,”^a”, “The”, “all”)

CommentsThe special characters ^ and $ represent the beginning and the end of the string, respec-tively.

The example will return the string “The man, a plan, a canal, panama!”.Only the a at the very beginning of the string changed.

The . (dot) character is used to represent any possible character, including whitespaceand newlines. For example, the pattern .ort can match the words fort, port, tort,but not ort. However, the pattern .*ort will match fort, report, ort, retort, andso on.

1.14. Using BracketsYou want to use the bracket characters ([]) to represent a subset of characters.

TechniqueUse brackets [] to represent a subset of characters.

<cfset pos = REFind(“ [A-Z]l”,”The Sun Also Rises”)>

CommentsThis expression looks for a space, followed by any uppercase letter, followed by the low-ercase letter l.The bracketed expression [A-Z] serves as a wildcard to the regularexpression parser to indicate:“any uppercase letter in the range of A to Z.”There is animplicit or among strings of letters in brackets.The pattern [dl]og will match dog andlog but not dlog.Adding a ^ (caret) to the beginning of the bracketed clause willimpose a negation on the characters contained in the brackets. For example, [^dl]ogwill match any sequence ending in og that is not preceded with a d or an l.

The brackets also allow you to specify a range of characters using the — (dash) char-acter. Here’s an example using the — character:

[0-9]?[0-9]/[0-9]?[0-9]/[0-9][0-9]

20 Chapter 1 String Manipulation

03 0672324628 CH01 6/8/05 11:07 AM Page 20

Page 44: ColdFusion MX Developer's Cookbook (Developer's Library)

Can you figure out what it is matching? It matches dates. It can match 1/1/01 or12/12/02 using the ? quantifier because the first digit of the month and day is optional.

1.15. Performing OR OperationsYou want to use the pipe (|) character to perform a logical OR operation andto group characters.

TechniqueUse the | (pipe) character and parentheses to perform a logical OR operation, as well asto group characters.

CommentsThe | (pipe) special character is used as a logical OR. Each character in the pattern isintrinsically joined with a logical AND, unless explicitly specified with the | character. Ifyou wanted a regular expression to match car or bar, you could use the patternc|bar.

You might have noticed with that last example that you could have also matched caror bar using brackets “[cb]ar”. It turns out that the | character has other uses; it canbe used to match sequences of characters as well.This is done with the parentheses ( )characters. Parentheses are used to group characters. Here’s an example using parenthesesand the | character:

(Mon)|(Tues)day

This example matches Monday or Tuesday.

1.16. Escaping Special CharactersYou want to use the backslash (\) character to escape special characters.

TechniqueUse the backslash (\) character to escape special characters.

<cfif NOT ReFind(“.+@.+\..+”, form.emailAddress)>

You entered an invalid email address. <cfabort>

</cfif>

CommentsThe \ character is used for escaping any quantifiers or special characters. Let’s look at apractical example, which validates an email address.To build this pattern, you deconstruct

211.16. Escaping Special Characters

03 0672324628 CH01 6/8/05 11:07 AM Page 21

Page 45: ColdFusion MX Developer's Cookbook (Developer's Library)

22 Chapter 1 String Manipulation

the email address. Email addresses start with a username .+. Next comes the @ sign, .+@,and then a domain name that contains at least one dot (you need to escape it).Therefore, .+@.+\..+ is the correct pattern. Here’s a code snippet that you can use:

The \ character is also used for a very handy feature called the back reference. Itallows you to use your groups (patterns in parentheses) again in your pattern or in yourreplacement.The back reference \1 represents the first group, \2 represents the second,and so on. Here’s an example that eliminates repeated words:

REReplace(“Echo Echo”,”(.+) +\1”,”\1”,”ALL”)

1.17. Using Character ClassesYou want to use character classes to represent a predefined subset of characters.

TechniqueUse character classes to represent a predefined subset of characters.

CommentsThe last group of special characters are known as “character classes.” Character classes arekeywords that represent a predefined class of characters. One example is [[:alnum:]],which is the same as [a-zA-Z0-9].They are listed in Table 1.2.

Table 1.2 Regular Expression Character Classes

Character Class Matches

:alpha: Any letter

:upper: Any uppercase letter

:lower: Any lowercase letter

:digit: Any digit (0–9)

:alnum: Any alphanumeric character

:xdigit: Any hexadecimal digit

:blank: A space or tab.

:space: A space, tab, newline, carriage return, or line feed

:print: Any printable character.

:punct: Any punctuation character

:graph: All printable characters except those in the space character class:cntrl: All characters not in the upper, lower, alpha, digit, punct, graph, print, or

xdigit classes

03 0672324628 CH01 6/8/05 11:07 AM Page 22

Page 46: ColdFusion MX Developer's Cookbook (Developer's Library)

2Working with Lists

2.0. IntroductionThe last chapter discussed how ColdFusion gives special treatment to delimited strings.These strings are even given a special nickname: lists.The following string is an exampleof a ColdFusion list:

apple,orange,grape,banana,peach

Lists, such as this list of fruit, are wonderful data structures in ColdFusion.They are plaintext, so they are easy to assemble.They are also common. Data import files often containlists. Better yet, HTML check boxes submit their results as comma-delimited lists. Finally,ColdFusion provides a complete function library for manipulating lists.

Once familiar with them, you will find yourself using ColdFusion lists throughoutyour CFML templates.They are simple yet powerful and are another reason why theCFML language is so popular among non-programmers.

This chapter looks at some common programming tasks involving lists. In doing so, itexplains key list concepts and includes some practical examples.

2.1. Creating ListsYou want to create a list.

TechniqueUse delimited strings to create lists.

Lists are very easy to create.You can create a list of fruit in one line of code:

<cfset fruitList = “apple,orange,grape,banana,peach”>

04 0672324628 CH02 6/8/05 11:07 AM Page 23

Page 47: ColdFusion MX Developer's Cookbook (Developer's Library)

CommentsYou can create the same list iteratively by tacking on values one at a time.

<cfset fruitList = “apple”>

<cfset fruitList = fruitList&”,orange”>

<cfset fruitList = fruitList&”,grape”>

<cfset fruitList = fruitList&”,banana”>

<cfset fruitList = fruitList&”,peach”>

You can also use the ListPrepend() and ListAppend() functions to add elementsto the beginning and end of a list, respectively. Both functions take as arguments the list,the value to be added, and an optional delimiter (again, the comma is used as thedefault). Both functions also return a copy of the list with the new item.Thus, you cansubstitute this line:

<cfset fruitList = fruitList&”,orange”>

with:

<cfset fruitList = ListAppend(fruitList,”orange”)>

NoteThe ColdFusion documentation actually discourages the use of ListAppend() and ListPrepend()

in favor of manually adding items to a list. Unfortunately, it does not give the reason why.

Like Peter Parker’s spider or Pamela Anderson’s surgeon, the delimiter is the source of alist’s power.You can choose any character you like as a delimiter, although the comma isthe default in ColdFusion. Be sure to choose one that you like because it is importantthat you maintain a consistent delimiter in your list.

2.2. Changing DelimitersYou want to change the delimiter that a list uses.

TechniqueUse the ListChangeDelims() function to change a list’s delimiter.

<cfset list1 = “elem1,elem2,elem3,elem4,elem5”>

<cfset list2 = ListChangeDelims(list1,”|”)>

<cfoutput>

List 1: #list1#<br>

List 2: #list2#<br>

</cfoutput>

24 Chapter 2 Working with Lists

04 0672324628 CH02 6/8/05 11:07 AM Page 24

Page 48: ColdFusion MX Developer's Cookbook (Developer's Library)

252.3. Extracting Elements

CommentsIt was love at first sight.Your delimiter seemed to be perfect for your list when you firststarted going out.Alas, you caught your delimiter cheating with certain list elements andit is now time to move on.What is to be done?

Fortunately, ColdFusion makes it easy to extract yourself from this potentially awk-ward situation.The ListChangeDelims() function will clean up your mess. Simplypass it the list you want to change, the new delimiter, and (optionally) the old delimiterand you are back in business.Who said breaking up is hard to do?

This function is used to change the delimiter from a comma (,) to a pipe (|).This canbe useful when you anticipate using the delimiter as a part of a data element in the list.

2.3. Extracting ElementsYou want to extract specific elements within a list.

TechniqueUse the ListGetAt() and ListToArray() functions to extract elements in a list.

<cfset fruitlist = “apple,orange,grape,banana,peach”>

<cfset thirdfruit = ListGetAt(fruitlist,3)>

<cfset fruitarray = ListToArray(fruitlist)>

<cfset fourthfruit = fruitarray[4]>

<cfoutput>

fruit 3: #thirdfruit#<br>

fruit 4: #fourthfruit#<br>

</cfoutput>

CommentsThere are two primary ways to extract elements from a ColdFusion list.The most popu-lar way is to use the ListGetAt() function. ListGetAt() takes a list, a position, andan optional delimiter as its arguments. It returns the value that is found at the specifiedposition in the list.

You use this technique previously to extract the third fruit element in the list:

<cfset thirdfruit = ListGetAt(fruitlist,3)>

NoteColdFusion lists use cardinal (or one-based) numbering. Therefore, you should use the index 1, not 0, to ref-

erence the first element in a list.

04 0672324628 CH02 6/8/05 11:07 AM Page 25

Page 49: ColdFusion MX Developer's Cookbook (Developer's Library)

The second way to inspect the contents of a list is to convert the list into an array anduse array indexing to retrieve the values.The ListToArray() function performs theconversion for you. Pass the function a list and an optional delimiter and it will return anindexed array.You can use this approach in the current example to get the fourth fruit:

<cfset fruitarray = ListToArray(fruitlist)>

<cfset fourthfruit = fruitarray[4]>

The use of arrays is covered in much more detail in the next chapter. However, you cansee that the expression fruitarray[4] is much easier on the wrists thanListGetAt(fruitlist,4). Converting your list into an array is a nice techniquewhen you will be extracting many elements from a single list.There is a potential per-formance boost to this as well, because indexed lookups take less time than do linearsearches in a list.

However, make sure that you are done modifying the list before you convert it intoan array. ColdFusion makes a copy of the list when it converts it. If you make changes tothe list following the conversion, you must re-convert the list or else make the samechanges to the array.

ColdFusion also supplies the following three functions to access the contents of alist—ListFirst(), ListRest(), and ListLast(). ListFirst() returns the firstelement of a list. ListLast() returns the last element of a list. ListRest() returns alist without its first element. LISP programmers might recognize ListFirst() andListRest() as the car and cdr functions of the recursive LISP programming lan-guage.

NoteUse the Trim() function to remove extra spaces surrounding delimiters in your list.

2.4. Handling Empty ValuesYou want to handle empty values in your list.

TechniqueUse a custom function to fix null values in a list.

<cfscript>

function ListFixNulls(list,delim)

{

ar = ArrayNew(1);

theval = “”;

thechar = “”;

pos = 1;

for (i=1; i lte Len(list); i = i + 1)

{

thechar = mid(list,i,1);

26 Chapter 2 Working with Lists

04 0672324628 CH02 6/8/05 11:07 AM Page 26

Page 50: ColdFusion MX Developer's Cookbook (Developer's Library)

272.4. Handling Empty Values

if (thechar is delim)

{

ar[pos] = theval;

pos = pos + 1;

theval = “”;

} else {

if (thechar is not chr(0))

{

theval = theval & thechar;

}

}

}

if (not(arrayisempty(ar)) or theval is not “”)

{

ar[pos] = theval;

}

return ar;

}

</cfscript>

<cfinclude template = “ListFixNulls.cfm”>

<cfset emplist = “10002,Jane,,Smith”>

<cfoutput>

With ListFixNulls()...<br>

<cfset emparray = ListFixNulls(emplist,”,”)>

<cfset id = emparray[1]>

<cfset firstname = emparray[2]>

<cfset middle = emparray[3]>

<cfset lastname = emparray[4]>

ID: #id#<br/>

First Name: #firstname#<br/>

Middle Initial: #middle#<br/>

Last Name: #lastname#<br/>

Without ListFixNulls()...<br>

<cfset id = ListGetAt(emplist,1)>

<cfset firstname = ListGetAt(emplist,2)>

<cfset middle = ListGetAt(emplist,3)>

<cfset lastname = ListGetAt(emplist,4)>

ID: #id#<br/>

First Name: #firstname#<br/>

Middle Initial: #middle#<br/>

Last Name: #lastname#<br/>

</cfoutput>

04 0672324628 CH02 6/8/05 11:07 AM Page 27

Page 51: ColdFusion MX Developer's Cookbook (Developer's Library)

28 Chapter 2 Working with Lists

CommentsMost historians attribute the ancient Indian mathematician Brahmagupta (598–670 AD)with the introduction of the number zero to modern numbering systems. He foreverchanged the way mathematicians think by recognizing the importance of acknowledgingthe “null value” in any mathematical system.

Unfortunately, the works of Brahmagupta were not consulted during the design phaseof the ColdFusion lists implementation. CFML list-processing functions completely dis-regard the null value, a fact which has long irked this ColdFusion developer. For exam-ple, consider the following table of employee names and IDs:

Employee ID,First Name,Middle Initial,Last Name

10001,John,H,Smith

10002,Jane,,Smith

10003,George,O,Smith

Although John and George both have middle initials, Jane does not. ColdFusion willthrow an “Invalid List Index” exception when you try to access the fourth ele-ment of Jane Smith’s list.The ListGetAt() function essentially removes all null valuesfrom the list (for example, “1,2,3” is equivalent to “1,,,,2,,,,,,,,3”).Thus, thetemplate returns the string “Smith” as the third element of the list instead of returningan empty string, as one might expect.

This phenomenon becomes a nightmare when dealing with associated lists that maycontain null values (like most data imports). Fortunately, there is a work-around.Theprevious technique shows a custom function (see Chapter 16,“User-Defined Functions,”for more about user-defined functions) that converts a list into array while preservingthe list’s null values.This function takes as arguments a list and a delimiter character andreturns the new array.

The function must not rely on the ColdFusion List API because those functions willignore null values. Instead, it must examine each character in the list and build the arrayvalues manually. Note that the function will not work with multi-character delimiters. Ileave this up to you to implement.

2.5. Changing Values in a ListYou want to change the values of specific elements within a list.

TechniqueUse the ListInsertAt(), ListSetAt(), and ListDeleteAt() functions to modifythe contents of a list.

<cfset list = “elt1,elt2”>

<cfset list1 = ListInsertAt(list,1,”elt0”)>

<cfset list2 = ListSetAt(list,1,”elt0”)>

<cfset list3 = ListDeleteAt(list,1)>

04 0672324628 CH02 6/8/05 11:07 AM Page 28

Page 52: ColdFusion MX Developer's Cookbook (Developer's Library)

<cfoutput>

Originial List: #list#<br>

With Element Inserted: #list1#<br>

With Element Set: #list2#<br>

With ElementDeleted: #list3#<br>

</cfoutput>

CommentsUpdating lists in ColdFusion is even easier than creating them. Use the

ListInsertAt() function to insert a new value into your list.The function takes thelist you are updating, the position you want to change, the value you want to insert, andan optional delimiter as arguments.The function confirms that you have supplied a validlist index and inserts the new value at the specified position, moving the original ele-ment and all subsequent elements over one spot in the list.

The ListSetAt() function uses the same syntax as ListInsertAt() but itsbehavior is slightly different. ListSetAt()replaces the old element at the specifiedposition with the new element.

The ListDeleteAt() function is the third list-modification function.The argu-ments for the ListDeleteAt() function are the list to be modified, the position thatshould be removed from the list, and an optional delimiter. ListDeleteAt() willreturn a copy of the list sans the element at the specified position.The previous technique uses these functions to modify a single list in three ways.

2.6. Searching a ListYou want to search a list for specific values.

TechniqueUse the ListFind() and ListFindNoCase() functions to search the elements of alist.

<cfset fruitList = “apple,orange,grape,banana,peach”><cfset pos = ListFind(fruitList,”grape”)><cfoutput>

The element was found at position #pos# in the list.</cfoutput>

CommentsHow can you determine whether a given list contains a specific element? Once again,CFML comes to the rescue by giving you the ListFind() and ListFindNoCase()functions.The arguments to both functions are the same: a list to search, a value tosearch for, and an optional delimiter to use when searching.These functions return theindex of the first element that matches the specified value. ListFind()performs a case-sensitive search, whereas ListFindNoCase() does not.

292.6. Searching a List

04 0672324628 CH02 6/8/05 11:07 AM Page 29

Page 53: ColdFusion MX Developer's Cookbook (Developer's Library)

The template in the previous example searches a list for the element “grape”.TheListFind() function returns the number 3 to indicate that the element in questionresides in the list’s third position.

2.7. Sorting a ListYou want to sort the elements in a list.

TechniqueUse the ListSort() function to sort a list.

<cfset fruitList = “apple,orange,grape,banana,peach”>

<cfset sortedList = ListSort(fruitList,”text”,”asc”)>

<cfoutput>#sortedlist#</cfoutput>

CommentsCFML also gives you the capability to sort your lists.The ListSort() function allowsyou to sort a list of elements in different ways.The arguments to ListSort() are thelist to sort, the sort type (that is, numeric, text, and textnocase), the sort order(such as asc[ending] or desc[ending]), and an optional delimiter. ListSort() returnsa copy of the sorted list.

The previous technique shows a template that performs an ascending text sort on alist.The result of the function is this list: “apple,banana,grape,orange,peach”.

NoteMacromedia introduced a subtle change to the ListSort() function in the new MX server. When using

the textnocase and desc options, MX returns elements that differ only in case in the opposite order as

when the textnocase and asc options are used. Older versions of ColdFusion did not change the order-

ing of elements that differed only in case.

2.8. Adding Qualifiers to a ListYou want to add qualifiers to the elements within a list.

TechniqueUse the ListQualify() function to qualify the elements of a list.

<cfset fruitList = “apple,orange,grape,banana,peach”>

<cfset qualifiedList = ListQualify(fruitList,”’”,”,”,”all”)>

<cfoutput>#qualifiedList#</cfoutput>

30 Chapter 2 Working with Lists

04 0672324628 CH02 6/8/05 11:07 AM Page 30

Page 54: ColdFusion MX Developer's Cookbook (Developer's Library)

312.9. Looping Through a List

CommentsDelimiters are a necessary evil in any list.A poorly chosen delimiter can render a listuseless. Imagine using the letter a as a delimiter in a list of names.That probably wouldnot work so well.The perfect delimiter is one that will never appear in the list’s data.Choosing this delimiter usually requires a prior knowledge of the characters that willappear in the list.

What should you do, then, if the element data in your list requires that the delimiterappear in the data fields as well? One technique you can use is to qualify the elements inyour list. Qualifying a list means using additional characters, other than the delimiter, toisolate the different elements. Single and double quotes are common list qualifiers.

Consider the following list of addresses:

8317 Morgans Way,1128 Blenheim Dr,804 W. Morgan St, Apt X2C

The string “Apt X2C” is clearly a continuation of the “804 W. Morgan St” addressand not an address on its own.You can eliminate this ambiguity by qualifying the ele-ments in the list:

“8317 Morgans Way”,”1128 Blenheim Dr”,”804 W. Morgan St, Apt X2C”

ColdFusion includes a function, ListQualify(), that will surround a list’s elementswith a qualifier of your choosing.The function accepts a list, a character or string qualifi-er, an optional delimiter, and an optional elements argument.The all elements optionwill put qualifiers around all elements in the list; the char option will put qualifiersaround alphabetic strings (numeric fields usually do not require qualifiers).

The example shown in this technique adds qualifiers to a list to produce the follow-ing output:

‘apple’,’orange’,’grape’,’banana’,’peach’

ListQualify() is a nice function to use when you are preparing a large list of data forimport into a database. Many import routines actually expect data to be in a qualified(quote-comma-delimited) format.

2.9. Looping Through a ListYou want to iterate over each element in a list.

TechniqueUse the <cfloop> tag with the list attribute to iterate over the elements in a list.

<cfset fruitList = “apple,orange,grape,banana,peach”>

<cfloop index=”fruit” list=”#fruitList#” delimiters=”,”>

<cfoutput>#fruit#</cfoutput><br/>

</cfloop>

04 0672324628 CH02 6/8/05 11:07 AM Page 31

Page 55: ColdFusion MX Developer's Cookbook (Developer's Library)

32 Chapter 2 Working with Lists

CommentsMy favorite list-related feature in ColdFusion is the built-in support for looping over alist of elements.The simplist way to do this is to use the <cfloop> tag and to specify itslist attribute.

The list attribute is, perhaps, the <cfloop> tag’s finest asset. In this mode,<cfloop> expects the following attributes: index (required—the variable name towhich each list element will be assigned), list (required—the list that is to be looped),and delimiters (optional—one or more delimiters to use in iterating over the list).Thetag will execute its body n-times, where n equals the number of elements in the list.Upon each iteration, the loop will assign the next element in the list to the variablenamed by the index parameter.

The <cfloop> tag will iterate over each fruit in the list, assigning a new value to thevariable fruit each time.The page output generated by the templates looks like this:

Apple

orange

grape

banana

peach

2.10. Looping Over a Structure’s Key ListYou want to iterate over the keys contained in a structure.

TechniqueUse the <cfloop> tag to iterate over a structure’s keylist.

<cfset p = StructNew()>

<cfset p.id = “10001”>

<cfset p.firstName = “Ryan”>

<cfset p.middleName = “Allen”>

<cfset p.lastName = “Hackney”>

<cfset p.city = “Red Stick”>

<cfset p.state = “LA”>

<cfloop index=”key” list=”#StructKeyList(p)#”>

<cfset value = StructFind(p,key)>

<cfoutput>#key# = #value#</cfoutput><br/>

</cfloop>

CommentsThe <cfloop> tag can be used to examine the contents of a structure. Structures, whichare covered in better detail in Chapter 4,“Structures,” are hash tables that contain an

04 0672324628 CH02 6/8/05 11:07 AM Page 32

Page 56: ColdFusion MX Developer's Cookbook (Developer's Library)

unlimited number of key/value pairs.You can use the StructKeyList() function toacquire a list of entry keys in a structure.You can then use the <cfloop> tag to iterateover these keys and evaluate the entry in the structure.The code shown in this techniquecreates a simple structure representing an employee and examines its contents by usingthe <cfloop> tag.The template produces the following output:

STATE = LA

LASTNAME = Hackney

ID = 10001

MIDDLENAME = Allen

CITY = Red Stick

FIRSTNAME = Ryan

2.11. Looping Until a List Is EmptyYou want to perform a conditional loop on a list that might change.

TechniqueUse the <cfloop> tag and its condition attribute to loop over the contents of adynamic list.

<cfset fruitList = “apple,orange,grape,banana,peach”>

<cfloop condition=”fruitList is not ‘’”>

<cfset fruit = ListFirst(fruitList)>

<cfset fruitList = ListRest(fruitList)>

<cfoutput>#fruit#</cfoutput><br/>

</cfloop>

CommentsAnother way to loop over a list is to use the <cfloop> tag with its condition attrib-ute in concert with the ListFirst() and ListRest() functions.This is useful whenyou will be modifying the contents of the list inside the body of the loop.The algorithmis to pop off the first element of the list continuously until the list is empty.The examplein this section implements this strategy.

In the example, fruitList is constantly reduced in size by assigning it the result ofthe ListRest() function.You therefore have greater control over the contents of thelist and the behavior of the loop.The loop will continue until the list is empty.You cancontrol how and when that condition arises.This level of control is often unnecessary,making the <cfloop list=”...”> approach the looping construct of choice ninetimes out of ten. However, keep this technique in your bag of tricks in case you need tochange the contents of your list in midstream.

332.11. Looping Until a List Is Empty

04 0672324628 CH02 6/8/05 11:07 AM Page 33

Page 57: ColdFusion MX Developer's Cookbook (Developer's Library)

34 Chapter 2 Working with Lists

2.12. Parsing Input FormsYou want to use lists to help parse the values in an input form.

TechniqueUse the <cfloop> tag to iterate over a collection of values contained in a single inputform field.

<html>

<body>

<cfif isdefined(“submitted”)>

<cfif isDefined(“fruitlist”) and ListLen(fruitList) gt 0>

These are the fruits you like:<br/>

<cfloop index=”fruit” list=”#fruitList#”>

<cfoutput>#fruit#</cfoutput><br/>

</cfloop>

<cfelse>

You hate fruit!

</cfif>

<cfelse>

<form action=”Checkboxes.cfm” method=”post”>

<cfoutput>

Which fruits do you like?<br>

<cfset fruitOptions = “Apple,Banana,Grape,Orange,Peach”>

<cfloop index=”option” list=”#fruitOptions#”>

<input type=”checkbox” name=”fruitList”value=”#option#”/>#option#<br/>

</cfloop>

<input type=”submit” name=”submitted” value=”Submit”>

</cfoutput>

</form>

</cfif>

</body>

</html>

CommentsColdFusion creates a list out of a form variable that has been defined multiple times onan input form. Consider, for example, the following URL submitted by a Web browser:

http://localhost/colors_form.cfm?color=red&color=blue&color=green

Notice that the variable color has three values. Obviously, ColdFusion cannot createthree unique variables with the same name, so it compensates by creating a single vari-able that is a list of three values. In other words, the value of the variable color is thestring “red,blue,green”.

04 0672324628 CH02 6/8/05 11:07 AM Page 34

Page 58: ColdFusion MX Developer's Cookbook (Developer's Library)

352.12. Parsing Input Forms

The example shown in this technique demonstrates this concept by creating a smallform that contains five check boxes with the same name.The template uses the loopingtechnique to examine the contents of the submitted form.

Notice that this example loops over two lists. It loops over the types of fruit that theuser submitted in lines 6–8. However, the example also loops over a list of options (lines16–19) to populate the input form.This is a nice way to save time typing while makingthe form more extensible.You can easily change the order and values of the options onthe form by modifying the fruitOptions list.

04 0672324628 CH02 6/8/05 11:07 AM Page 35

Page 59: ColdFusion MX Developer's Cookbook (Developer's Library)

04 0672324628 CH02 6/8/05 11:07 AM Page 36

Page 60: ColdFusion MX Developer's Cookbook (Developer's Library)

3Arrays

3.0. IntroductionAn array is a data type containing an ordered collection of variables. Items in an arrayare referred to as array elements and are referenced by their index (or numerical position)in the array.

You use arrays when you have a collection of variables and need to store them in adefined order. Like lists (discussed in Chapter 2,“Working with Lists”), arrays supportvariable order—you can explicitly reference the value stored in a given position of thearray.Although lists only store simple variables like strings and numbers, arrays can storecomplex data types, such as structures, queries, and even other arrays. If you need tostore complex data types in a collection but do not need them in a defined order, youmay want to look into using the ColdFusion data type structure, discussed in Chapter 4,“Structures.”

This chapter shows you how to iterate over array element values, manipulate elementvalues, and sort an array. It also explains how and when to use multidimensional arraysand how and when to use array aggregate functions.

3.1. Creating an ArrayYou want to create a new array.

TechniqueUse the ArrayNew() function to create a new ColdFusion Array object.

<cfset aPetSounds = ArrayNew(1)>

05 0672324628 CH03 6/8/05 11:07 AM Page 37

Page 61: ColdFusion MX Developer's Cookbook (Developer's Library)

38 Chapter 3 Arrays

CommentsColdFusion arrays are different than arrays in many other programming languages in thatColdFusion arrays are sized dynamically.A dynamically sized array is one that allows forexpansion as elements are added—the programmer does not need know the size of thearray when it is declared. Instead, ColdFusion sizes the array as the number of elementsexceeds the size that ColdFusion initially appropriated.

This dynamic sizing provides flexibility in programming but can also cause a per-formance hit—especially for large arrays, because ColdFusion essentially has to guesshow large the array will eventually be. So if you know the maximum number of ele-ments your array will contain, ColdFusion provides the ArrayResize() function toforce a minimum size. ArrayResize() accepts two parameters, the array to resize andthe minimum size to set that array. ColdFusion documentation suggests using theArrayResize() function immediately following an array declaration that will containmore than 500 elements.

Multidimensional arrays are covered later in this chapter—until then you’ll use onlysingle dimensional arrays, created by passing a value of 1 to the ArrayNew() function.

NoteAs a best practice, all arrays in this chapter begin with the letter a, as in aArrayName.

3.2. Adding an Element to an ArrayYou want to add an element to an array.

TechniqueYou add elements to an array by statically referencing the index of the element you wantto insert, by using the ArrayAppend() function, or by using the ArrayPrepend()function.

<!---add element by index--->

<cfset aPetSounds[1] = “You Still Believe In Me”>

<cfset aPetSounds[2] = “That’s Not Me”>

<!---add element using ArrayAppend--->

<cfset ArrayAppend(aPetSounds, “Don’t Talk (Put Your Head On My Shoulder)”)>

<!---add element using ArrayPrepend--->

<cfset ArrayPrepend(aPetSounds, “Wouldn’t It Be Nice”)>

05 0672324628 CH03 6/8/05 11:07 AM Page 38

Page 62: ColdFusion MX Developer's Cookbook (Developer's Library)

CommentsAfter you’ve created an array, the natural next step is to populate its elements. (To createan array, see section 3.1,“Creating an Array.”) One way to set the index value of a givenelement in an array is to reference the element you want to populate by index and set itsvalue explicitly.This code is an example of creating a new array named aPetSoundsand setting the first and second element to the strings “You Still Believe In Me”and “That’s Not Me”, respectively, by reference. (Pet Sounds, of course, is an album bythe Beach Boys—often considered their masterpiece.)

Notice that ColdFusion uses 1-based numbering arrays—the first array element is inposition 1. Many programming languages use 0-based numbering arrays, which place thefirst element in position 0.

Another way to add an element to an array is to use either the ArrayAppend() orArrayPrepend() function.This method of adding elements ensures you don’t place avalue in an unintended index of the array.

ArrayPrepend() will prepend your value to the array, making it the first elementand pushing all other elements down an index.This is a useful function if you need toadd an element to the beginning of an array, but aren’t worried about the other ele-ments’ index values. For example, in the previous technique, Wouldn’t It Be Nicegains an index of 1, whereas You Still Believe In Me and That’s Not Me nowhave index values of 2 and 3, respectively (even though their index values were givenexplicitly).

ArrayAppend() adds your element to the end of an array, making it the last elementin the array, and leaving the other elements where they are. Use the ArrayAppend()function when you need to maintain the integrity of the array’s current index. Noticethat Don’t Talk (Put Your Head On My Shoulder) is now a part of thepetSounds array, but it has simply been “tacked on,” and has an index value of 4.Thisleaves the first three song titles’ index values untouched.

3.3. Displaying a Value in an ArrayYou want to retrieve and display a value stored in an array.

TechniqueUse <cfoutput> tags and reference the desired value by index to retrieve and displaythe value stored in a specific array element.

<cfoutput>

Song 1: #aPetSounds[1]#<br>

Song 2: #aPetSounds[2]#<br>

393.3. Displaying a Value in an Array

05 0672324628 CH03 6/8/05 11:07 AM Page 39

Page 63: ColdFusion MX Developer's Cookbook (Developer's Library)

Song 3: #aPetSounds[3]#<br>

Song 4: #aPetSounds[4]#

</cfoutput>

CommentsExecuting this code produces the following output:

Song 1: Wouldn’t It Be Nice

Song 2: You Still Believe In Me

Song 3: That’s Not Me

Song 4: Don’t Talk (Put Your Head On My Shoulder)

If you attempt to reference an element that does not exist in your array, ColdFusionthrows an ArrayBoundException exception. Refer to Chapter 8,“ExceptionHandling,” for more information on exceptions in CFMX.

3.4. Looping over an ArrayYou want to iterate over each element in an array.

TechniqueUse <cfloop> to iterate over each element in an array.

Pet Sounds Track Listing

<hr>

<cfoutput>

<!---loop over array and display each element value--->

<cfloop from=”1” to=”#ArrayLen(aPetSounds)#” index=”i”>

Song #i#: #aPetSounds[i]#<br>

</cfloop>

</cfoutput>

CommentsThis example revisits the aPetSounds array and loops from 1 to the length of the arrayto extract and display the value of each element. Looping over an array to display its val-ues ensures that you won’t reference an index that doesn’t exist.This code also showsthat you can use ColdFusion expressions and variables to reference indexes within anarray—in this case, you use the current index of the loop to retrieve the associated indexin the array.

NoteThis code introduces the ArrayLen() function. ArrayLen() accepts a single argument: the array in

question. Similar to the Len() function, which counts the number of characters in a string, ArrayLen()

returns the number of elements in an array.

40 Chapter 3 Arrays

05 0672324628 CH03 6/8/05 11:07 AM Page 40

Page 64: ColdFusion MX Developer's Cookbook (Developer's Library)

413.6. Sorting an Array

3.5. Manipulating Array ValuesYou want to access or modify specific elements within an array.

TechniqueManipulate elements in a populated array by iterating over the array and performing thedesired function during each iteration of the loop.

<!---Manipulate each element to append song number--->

<cfloop from=”1” to=”#ArrayLen(aPetSounds)#” index=”i”>

<cfset aPetSounds[i] = “Song “ & i & “: “ & aPetSounds[i]>

</cfloop>

CommentsArrays are used in Web applications to store ordered collections of related data. Naturally,as a user progresses through an application, data will change.Therefore, you need a wayto manipulate the values of an array in order to perform functions on element values.Say you need to add the track number to each value in the aPetSounds array.You cando so by looping over the array values and manipulating the string to include the loopnumber, resulting in the desired value.

Notice in the first cfloop statement that the value of the current element is refer-enced and a new value is set in the same line.This inline variable manipulation is accept-able in CFML.You also use the index variable i to insert the song number—a simpleexample of benefiting from the order functionality provided by the array data type.To display the new values with the track number prepended to the value, execute thefollowing code:

Pet Sounds Track Listing

<hr>

<cfoutput>

<!---loop over array and display each element value--->

<cfloop from=”1” to=”#ArrayLen(aPetSounds)#” index=”i”>

#aPetSounds[i]#<br>

</cfloop>

</cfoutput>

3.6. Sorting an ArrayYou want to sort the elements of an array.

TechniqueUse the ArraySort() function to sort the elements of an array.

<cfset abcList = “c,B,b,A,C,a”>

05 0672324628 CH03 6/8/05 11:07 AM Page 41

Page 65: ColdFusion MX Developer's Cookbook (Developer's Library)

42 Chapter 3 Arrays

<cfset aAbcArray = ArrayNew(1)>

<cfloop from=”1” to=”#ListLen(abcList)#” index=”i”>

<cfset aAbcArray[i] = listGetAt(abcList,i)>

</cfloop>

aAbcArray:<br/>

<cfoutput>

<cfloop from=”1” to=”#ArrayLen(aAbcArray)#” index=”i”>

element #i#: # aAbcArray[i]#<br/>

</cfloop>

</cfoutput>

<p/>

aAbcArray sorted with “text” attribute:<br/>

<cfset ArraySort(aAbcArray,”text”)>

<cfoutput>

<cfloop from=”1” to=”#ArrayLen(aAbcArray)#” index=”i”>

element #i#: # aAbcArray[i]#<br/>

</cfloop>

</cfoutput>

<p/>

aAbcArray sorted with “text” and “desc” attributes:<br/>

<cfset ArraySort(aAbcArray,”text”,”desc”)>

<cfoutput>

<cfloop from=”1” to=”#ArrayLen(aAbcArray)#” index=”i”>

element #i#: # aAbcArray[i]#<br/>

</cfloop>

</cfoutput>

<p/>

aAbcArray sorted with “textnocase” attribute:<br/>

<cfset ArraySort(aAbcArray,”textnocase”)>

<cfoutput>

<cfloop from=”1” to=”#ArrayLen(aAbcArray)#” index=”i”>

element #i#: # aAbcArray[i]#<br/>

</cfloop>

</cfoutput>

<p/>

aAbcArray sorted with “textnocase” and “desc” attributes:<br/>

<cfset ArraySort(aAbcArray,”textnocase”,”desc”)>

<cfoutput>

<cfloop from=”1” to=”#ArrayLen(aAbcArray)#” index=”i”>

element #i#: # aAbcArray[i]#<br/>

</cfloop>

</cfoutput>

05 0672324628 CH03 6/8/05 11:07 AM Page 42

Page 66: ColdFusion MX Developer's Cookbook (Developer's Library)

433.6. Sorting an Array

CommentsThe ArraySort() function sorts arrays numerically or alphabetically. It accepts tworequired arguments, the array to be sorted and the sort type, and one optional argument,sort order (which, if not provided, defaults to ascending).

Using ArraySort(), the sort type argument can be numeric, text, or textnocase. If sort type is numeric, the array elements are sorted numerically inascending or descending order based on the sort order argument. If no sort order is pro-vided, ArraySort() uses ascending, the default.

If sort type is text, the array elements are sorted alphabetically taking case intoaccount. In text sorts, sort order ascending starts with uppercase A and ends with lower-case z, descending starts with lowercase z and ends with uppercase A. If sort type istextnocase, the array elements are sorted alphabetically without taking case intoaccount.That is, if sort order is ascending, A/a precedes a B/b. If sort order is descend-ing, a Z/z precedes a Y/y.Take a look at what happens when you execute the code inthis technique:

aAbcArray:

element 1: c

element 2: B

element 3: b

element 4: A

element 5: C

element 6: a

aAbcArray sorted with “text” attribute:

element 1: A

element 2: B

element 3: C

element 4: a

element 5: b

element 6: c

aAbcArray sorted with “text” and “desc” attributes:

element 1: c

element 2: b

element 3: a

element 4: C

element 5: B

element 6: A

aAbcArray sorted with “textnocase” attribute:

element 1: a

element 2: A

element 3: b

05 0672324628 CH03 6/8/05 11:07 AM Page 43

Page 67: ColdFusion MX Developer's Cookbook (Developer's Library)

element 4: B

element 5: c

element 6: C

aAbcArray sorted with “textnocase” and “desc” attributes:

element 1: C

element 2: c

element 3: B

element 4: b

element 5: A

element 6: a

3.7. Multidimensional ArraysYou want to create an array with more than one dimension.

TechniqueUse ArrayNew(), passing in as a parameter the number of dimensions you require, tocreate a multidimensional array.

<!---Create a two dimensional aBeachBoysAlbums array--->

<cfset aBeachBoysAlbums = ArrayNew(2)>

<!---Build first album array, Surfin’ Safari--->

<cfset aBeachBoysAlbums[1][1] = “Surfin’ Safari”>

<cfset aBeachBoysAlbums[1][2] = “County Fair”>

<cfset aBeachBoysAlbums[1][3] = “Ten Little Indians”>

<!---Build second album array, Surfin’ USA--->

<cfset aBeachBoysAlbums[2][1] = “Surfin’ USA”>

<cfset aBeachBoysAlbums[2][2] = “Farmer’s Daughter”>

<cfset aBeachBoysAlbums[2][3] = “Miserlou”>

<!---Build third album array, Surfer Girl--->

<cfset aBeachBoysAlbums[3][1] = “Surfer Girl”>

<cfset aBeachBoysAlbums[3][2] = “Catch a Wave”>

<cfset aBeachBoysAlbums[3][3] = “The Surfer Moon”>

CommentsA multidimensional array is an array of arrays rather than an array of single values. Untilthis point in the chapter, one-dimensional arrays have been covered, and the array ele-ments have all been simple values—the name of a song or a letter of the alphabet. In amultidimensional array, you use the array elements to store other arrays.

44 Chapter 3 Arrays

05 0672324628 CH03 6/8/05 11:07 AM Page 44

Page 68: ColdFusion MX Developer's Cookbook (Developer's Library)

ColdFusion allows you to define up to three dimensions in an array with a call to theArrayNew() function. ArrayNew() takes one argument—1, 2, or 3—depending onhow many dimensions you need.

This code is an example of creating a two-dimensional array. It continues using theBeach Boys as a model and uses a two-dimensional array to store album information inorder of release. For this example, you use only the first three songs from each of theirfirst three releases.

If you want to display the values stored in the inner dimensions of an array, it is nec-essary first to get a handle on each element. Using cfloop is the best way to do so.Remember, you need exactly as many loops as you have dimensions in the array.

3.8. Creating Arrays with More Than ThreeDimensions

You want to create an array with more than three dimensions.

TechniqueDefine multiple dimensions in an array by creating three dimensions at a time withArrayNew().

<!---create three dimensional aDeepArray array--->

<cfset aDeepArray = ArrayNew(3)>

<!---build nine dimensions--->

<cfset aDeepArray[1][1][1] = ArrayNew(3)>

<cfset aDeepArray[1][1][1][1][1][1] = ArrayNew(3)>

<cfset aDeepArray[1][1][1][1][1][1][1][1][1] = “I’m in the ninth dimension”>

<!----display first element in ninth dimension--->

<cfoutput>

#aDeepArray[1][1][1][1][1][1][1][1][1]#

</cfoutput>

CommentsAlthough ArrayNew()lets you define only three dimensions, should the need arise youcan bypass this constraint by setting any of the three dimension values to an array itselfand repeat until you have the dimension depth you require.The code in this exampleplaces a string value in the lowly ninth dimension.

453.8. Creating Arrays with More Than Three Dimensions

05 0672324628 CH03 6/8/05 11:07 AM Page 45

Page 69: ColdFusion MX Developer's Cookbook (Developer's Library)

46 Chapter 3 Arrays

3.9. Array Aggregate FunctionsYou want to perform aggregate functions on array elements.

TechniqueUse ColdFusion array aggregate functions to perform a function on all elements withinan array.

<!---Create aArray array and set array values--->

<cfset numList = “0,5,22,7,31”>

<cfset aArray = ListToArray(numList)>

aArray aggregate functions

<hr>

<cfoutput>

<!---Perform aggregate functions on aArray and display results--->

Maximum Value: #ArrayMax(aArray)#<br>

Minimum Value: #ArrayMin(aArray)#<br>

Sum: #ArraySum(aArray)#<br>

Average: #ArrayAvg(aArray)#

</cfoutput>

CommentsAggregate functions are functions executed on multiple values—array aggregate func-tions are functions executed on each array element value.

Table 3.1 defines the four functions available in ColdFusion MX.

Table 3.1 CFMX Array Aggregate Functions

Function Return Value

ArrayMax(array) Returns the maximum numeric value in array.

ArrayMin(array) Returns the smallest numeric value in array.

ArrayAvg(array) Returns the numeric average of all values in array.ArraySum(array) Returns the numeric sum of all values in array.

Two exceptions of note when dealing with array aggregate functions are as follows:n If there is a non-numeric value in an array passed into an aggregate function,

ColdFusion throws a runtime exception.n If the array passed into an aggregate function is empty, each of the functions

returns a 0.

05 0672324628 CH03 6/8/05 11:07 AM Page 46

Page 70: ColdFusion MX Developer's Cookbook (Developer's Library)

473.10. Array Utility Functions

Note that ColdFusionMX returns 0 when an empty array is passed into an array aggre-gate function. ColdFusion 5 returned infinity.

3.10. Array Utility FunctionsYou want to perform utility functions on arrays.

TechniqueUse ColdFusion array utility functions.

<cfset aNewArray = ArrayNew(3)>

CommentsYou have used a number of CFMX array utility functions in various techniquesthroughout this chapter.Table 3.2 defines each of the array utility functions, includingones you haven’t yet used. Don’t worry if you don’t understand them all yet—the moreyou work with arrays, the more you’ll find the need to reference this table.

Table 3.2 ColdFusion Array Utility Functions

Function Return Value

ArrayAppend(array, value) Places value in the (array length plus 1) element ofthe specified array. Returns true if successful.

ArrayClear(array) Deletes all values from the specified array. Returnstrue if successful.

ArrayDeleteAt(array, index) Deletes the value at index in the specified array.All elements with an index greater than index willbe offset by -1. Returns true if successful.ThrowsInvalidArrayIndexException if index is not avalid index for array.

ArrayInsertAt Inserts value at index of array.The index for (array, index, value) elements with an index greater than index will be

offset by 1. Returns true if successful. Throws theInvalidArrayIndexException exception ifindex is not a valid index for array.

ArrayNew(dimension) Creates an array of the specified dimension, whichmust be 1, 2, or 3.

ArrayPrepend(array, value) Places value in first element of specified the array.All indexes are offset by 1. Returns true if successful.

05 0672324628 CH03 6/8/05 11:07 AM Page 47

Page 71: ColdFusion MX Developer's Cookbook (Developer's Library)

ArrayResize(array, size) Resets array length to the specified size. Returnstrue if successful.

ArraySet(array, startIndex, Sets elements from index startIndex to endIndexendIndex, value) to specified value in array. Returns true if suc-

cessful.

ArraySort(array, sortType Sorts all elements in array by sortType (numeric,[,order]) text, or textnocase) in specified order (asc or

desc). If array contains anything other than simplevalues, ArraySort throwsArraySortSimpleValueException exception. Ifarray contains non-numeric values and sortType isnumeric, ArraySort throws ValueNotNumericexception. Returns true if successful.

ArraySwap(array, index1, Swaps the values at index1 and index2 of specified index2) array. Throws ArraySwapRangeException

exception if either index1 or index2 is an invalidindex for array. Returns true if successful.

ArrayToList(array Returns a list delimited by delimiter (a comma by [, delimiter]) default) containing the values in array.Throws

ArrayNotOneDimensionException exception ifarray contains more than one dimension.

ListToArray(list Returns an array populated with the contents of [, delimiter]) list using delimiter to specify indexes. Empty

values in list are ignored.

3.11. Array Information FunctionsYou want to retrieve information about an array object.

TechniqueUse ColdFusion array information functions to retrieve information about an arrayobject.

<cfset aNewArray = ArrayNew(3)>

CommentsArray Information functions are useful for gathering information about array objects.There are three ColdFusion array information functions, described in detail in Table 3.3.

48 Chapter 3 Arrays

Table 3.2 Continued

05 0672324628 CH03 6/8/05 11:07 AM Page 48

Page 72: ColdFusion MX Developer's Cookbook (Developer's Library)

493.11. Array Information Functions

Table 3.3 ColdFusion Array Utility Functions

Function Return Value

ArrayIsEmpty(array) Determines whether the ColdFusion array objectarray is empty of elements. Returns true if empty.

ArrayLen(array) Returns the number of elements found in array.IsArray(array [, dimension]) Determines whether array is a ColdFusion array

object. If dimension is defined, determineswhether the element contained in dimension is aColdFusion array object. Returns true if the itemis an array.

05 0672324628 CH03 6/8/05 11:07 AM Page 49

Page 73: ColdFusion MX Developer's Cookbook (Developer's Library)

05 0672324628 CH03 6/8/05 11:07 AM Page 50

Page 74: ColdFusion MX Developer's Cookbook (Developer's Library)

4Structures

4.0. IntroductionA structure is a complex ColdFusion data type containing key/value pairs of unsorteddata.

You use a structure to store data when you want to create an unordered collection ofassociated keys and values.Table 4.1 shows an example of how you might imagine thedata type in the form of a table.This example uses the University of Alabama and theirmost recent NCAA Division 1 Football National Championship.

Table 4.1 Representing a Structure

Key Value

GameDate Jan 1, 1993

Opponent The University of MiamiCoach Gene Stallings

Those familiar with other programming languages might recognize this key/value pairconcept as being an associative array. If so, you will be happy to know that you can referto elements in a structure using traditional dot notation. If you aren’t familiar with asso-ciative arrays, no worries—this chapter defines and discusses their similarities.

This chapter discusses the many advantages of using structures to store data.You learnhow to create, populate, refer to, loop over, and sort structures.You also might learn a bitabout the great football tradition of the University of Alabama Crimson Tide.

06 0672324628 CH04 6/8/05 11:07 AM Page 51

Page 75: ColdFusion MX Developer's Cookbook (Developer's Library)

52 Chapter 4 Structures

4.1. Creating a StructureYou want to create a new structure.

TechniqueCreate a ColdFusion structure explicitly by using the StructNew() function or implic-itly by setting a key/value pair in a new structure.

<!---create stMyFirstStruct structure--->

<cfset stMyFirstStruct = StructNew()>

<!---create stAnotherStruct structure and populate new key someKey--->

<cfset stAnotherStruct.someKey = “someValue”>

CommentsThere are two ways to create a structure in ColdFusion.The first is to use theStructNew() function.The first example in the technique shown here illustrates howto create a structure using this function.The other way to create a structure is to simplyset a key/value pair inside the structure, thereby creating the structure and an element inthat structure with a single line of code.The second example in the current techniqueuses only a single line of code to create a structure and to populate an element with thekey someKey and the value “someValue”.

NoteAs a best practice, all structures in this chapter begin with the letters st, as in stStructureName,

except for those defined by ColdFusion, such as CGI and the named scopes.

4.2. Using Structure Information FunctionsYou want to inspect a structure using ColdFusion structure information func-tions.

TechniqueUse IsStruct(), StructIsEmpty(), StructKeyExists(), and StructKeyList() to getinformation about a structure.

<cfoutput>

<!---determine if cgi is a structure--->

is CGI a structure? #IsStruct(cgi)#<br>

<!---determine if structure cgi is empty--->

is the CGI structure empty? #StructIsEmpty(cgi)#<br>

<!---determine if key HTTP_USER_AGENT exists in structure cgi--->

does the CGI structure contain a HTTP_USER_AGENT key?

06 0672324628 CH04 6/8/05 11:07 AM Page 52

Page 76: ColdFusion MX Developer's Cookbook (Developer's Library)

534.3. Using Structure Management Functions

#StructKeyExists(cgi,”HTTP_USER_AGENT”)#<br>

<!---Display all keys in structure cgi--->

What keys does the CGI structure contain? #StructkeyList(cgi)#<br>

</cfoutput>

CommentsTable 4.2 defines all four CFMX structure information functions and their return values.

Table 4.2 CFMX Structure Information Functions

Function Return Value

IsStruct(variable) Returns true if variable is a valid structure,false if it is not.

StructCount(structure) Returns the number of keys in structure.

StructIsEmpty(structure) Returns true if structure contains no ele-ments, false if it contains one or more.

StructKeyExists(structure, key) Returns true if key is a valid key in structure,false if it is not.

Notice the code in the previous technique doesn’t include a call to StructNew(), nordoes it create a value for the HTTP_USER_AGENT key.Actually, it doesn’t create any ofthe keys listed in the output of the StructKeyList() function.The reason? The CGIstructure is available for manipulation because it is a CFMX named variable scope.Allnamed variable scopes in CFMX are made available as structures.

NoteCFMX, unlike previous versions of ColdFusion, provides the Caller, Client, Server, and Variables

scopes as structures.

4.3. Using Structure Management FunctionsYou want to manage a structure using ColdFusion structure management functions.

Technique

<cfset structAppend(stStructA,stStructB)>

CommentsStructAppend() is one of nine CFMX structure management functions.Table 4.3defines all nine CFMX structure management functions and describes their functionalities.

06 0672324628 CH04 6/8/05 11:07 AM Page 53

Page 77: ColdFusion MX Developer's Cookbook (Developer's Library)

54 Chapter 4 Structures

Table 4.3 CFMX Structure Management Functions

Function Functionality

StructAppend(structureA, Appends elements in structureA to structureB[, overwrite]) structureB. If overwrite is false, the

value for a duplicate element is not copied.If its true, it is copied.The default is true.Returns true if the operation is successful;false if not.

StructClear(structure) Removes all keys and values from structure. Returns true if the operationis successful; false if not.

StructCopy(structure) Copies and returns structure with thesame keys and values. Note that all elementsare copied by value except nested structures,which are copied by reference.

StructDelete(structure, key Deletes key and its corresponding value [, booleanReturn]) from structure. If booleanReturn is

true, returns value boolean true if keyexists and false if not. If booleanReturnis false, the return value is true.booleanReturn is false by default.

StructFind(structure, key) Finds key in structure and returns itscorresponding value. If key does not exist instructure, throws a runtimeIllegalStructAccessException excep-tion.

StructInsert(structure, key, value ) Inserts new element into structure with [, overwrite] key and value. If overwrite is false, the

value for a duplicate element is not copied.If its true, it is copied.The default isfalse. Returns true if the operation issuccessful; false if not. If key exists andoverwrite is false, throws aStructInsertException exception.

StructNew() Creates and returns a new, empty structure.

StructSort(structure [, sortType Sorts structure or element structure of [ , order] ] [, structureReference based onstructureReference]| sortType and order. Returns an array of

structures populated with sorted key names.StructUpdate(structure, key, value) Updates structure and replaces value in

element key to value. If key does not existin structure, throws a runtimeIllegalStructAccessException excep-tion.

06 0672324628 CH04 6/8/05 11:07 AM Page 54

Page 78: ColdFusion MX Developer's Cookbook (Developer's Library)

554.4. Inserting Values into a Structure

The CFMX structure management functions are for managing structures inside yourapplication. Be careful when manipulating the ColdFusion named scope structures, asyou might experience unintended results.

NoteDo not use StructClear() to clean up your session variables, because this call will also remove the

CFID and CFTOKEN variables, effectively destroying the session as opposed to clearing the session vari-

ables. Use StructDelete() if you truly want to clear the session variables. For more on sessions, see

Chapter 7, “Application Flow.”

4.4. Inserting Values into a StructureYou want to insert values into a structure.

TechniqueUse StructInsert() to insert data into a structure.

<!---create parent structure stUndefeated--->

<cfset stUndefeated = Structnew()>

<!---create structure for 1992 team--->

<cfset stTide1992 = StructNew()>

<!---populate stTeam1992 structure using StructInsert() function--->

<cfset StructInsert(stTide1992,”Year”,”1992”)>

<cfset StructInsert(stTide1992,”Coach”,”Gene Stallings”)>

<cfset StructInsert(stTide1992,”Victories”,”13”)>

<cfset StructInsert(stTide1992,”TotalPoints”,”366”)>

<cfset StructInsert(stTide1992,”TotalOpponentPoints”,”122”)>

<!---insert stTeam1992 into the parent stUndefeated structure--->

<cfset StructInsert(stUndefeated,” stTide1992”,stTide1992)>

<!---create structure for 1979 team--->

<cfset stTide1979 = StructNew()>

<!---populate stTeam1997 structure using StructInsert() function--->

<cfset StructInsert(stTide1979,”Year”,”1979”)>

<cfset StructInsert(stTide1979,”Coach”,”Paul Bryant”)>

<cfset StructInsert(stTide1979,”Victories”,”12”)>

<cfset StructInsert(stTide1979,”TotalPoints”,”383”)>

<cfset StructInsert(stTide1979,”TotalOpponentPoints”,”67”)>

<!---insert stTeam1992 into the parent stUndefeated structure--->

<cfset StructInsert(stUndefeated,” stTide1979”,stTide1979)>

CommentsAfter you create your structure, the natural next step is to populate it with data and oth-erwise manipulate the information stored therein.

06 0672324628 CH04 6/8/05 11:07 AM Page 55

Page 79: ColdFusion MX Developer's Cookbook (Developer's Library)

56 Chapter 4 Structures

To simply place a key/value pair into a structure, you use the StructInsert()function. StructInsert() accepts four arguments—the structure into which you needto insert the element, the key, the value, and an optional Boolean fourth argument defin-ing whether you want to overwrite a value should the key you are attempting to insertalready exist.

The previous technique shows an example of creating a structure of structures thatstore simple string data about the associated years’ undefeated teams.

To illustrate inserting data into a structure, there’s a structure of structures representingthe University of Alabama’s last two undefeated national championship teams.TheCrimson Tide had two undefeated national championship teams in 13 years—one in1979 and one in 1992.

Remember though that there will be no inherent order in the parent structure, soyou can’t retrieve the teams in order by year until you use StructSort(), discussedlater in this chapter. If you need to store the data in order, you use the CFMX data typeArrays, discussed in detail in Chapter 3,“Arrays.”There is no guarantee as to the orderof the elements in a structure—in fact, the very nature of a structure dictates that there isno order to its elements.

4.5. Updating Values in a StructureYou want to update an existing value in a structure.

TechniqueUse StructUpdate() to update existing key/value pairs in a structure.

<!---create the stTide1979 structure--->

<cfset stTide1979 = StructNew()>

<!---populate stTide1979 structure using StructInsert() function--->

<cfset StructInsert(stTide1979,”Coach”,”Paul Bryant”)>

<cfoutput>

<!---display Coach value before update--->

Before Update: #StructFind(stTide1979,”Coach”)#<br>

</cfoutput>

<!---update Coach key in stTide1979 structure--->

<cfset StructUpdate(stTide1979,”Coach”,”Paul (Bear) Bryant”)>

<cfoutput>

<!---display Coach value after update--->

After Update: #StructFind(stTide1979,”Coach”)#

</cfoutput>

CommentsStructUpdate() accepts three arguments: the structure to update, the existing key inthe structure, and the new value to be associated with that key.The example here

06 0672324628 CH04 6/8/05 11:07 AM Page 56

Page 80: ColdFusion MX Developer's Cookbook (Developer's Library)

574.6. Displaying the Value of an Element in a Structure Using the Key Name

updates the value of the key coach from Paul Bryant to Paul (Bear) Bryant.Calling StructUpdate() with a key that does not exist in the target structure resultsin an IllegalStructAccessException exception.

4.6. Displaying the Value of an Element in aStructure Using the Key Name

You need to display the value of a structure element using the key name.

TechniqueUse StructFind() to reference the value of an element in a structure using the keyname.

<!---set variable theKey equal to string Coach--->

<cfset theKey = “Coach”>

<!---create the stTide1979 structure--->

<cfset stTide1979 = StructNew()>

<!---populate stTide1979 structure using StructInsert() function--->

<cfset StructInsert(stTide1979,theKey,”Paul Bryant”)>

<cfoutput>

<!---display Coach value before update--->

Before Update: #StructFind(stTide1979,theKey)#<br>

</cfoutput>

<!---update Coach key in stTide1979 structure--->

<cfset StructUpdate(stTide1979,theKey,”Paul (Bear) Bryant”)>

<cfoutput>

<!---display Coach value after update--->

After Update: #StructFind(stTide1979,theKey)#

</cfoutput>

CommentsThe technique in section 4.5 uses StructFind() to display the value of the Coachelement in the stTide1979 structure.The technique in this section displays the sameinformation but uses an expression to reference the desired value instead of the literalstring name of the key. StructFind() is one of two ways to reference elements of astructure—section 4.7 describes the other.

06 0672324628 CH04 6/8/05 11:07 AM Page 57

Page 81: ColdFusion MX Developer's Cookbook (Developer's Library)

58 Chapter 4 Structures

4.7. Using Dot NotationYou want to use dot notation to manipulate the contents of a structure.

TechniqueUse dot notation or one of two other methods to insert values into and retrieve valuesfrom a structure.

<!---create stTide2003 structure---

<cfset stTide2003 = StructNew()>

<!---set ‘coach’ value using dot notation--->

<cfset stTide2003.Coach = “Mike Price”>

<!---build stQuarterbacks structure, populate with three values--->

<cfset stQuarterbacks.starter = “Brodie Croyle”>

<cfset stQuarterbacks.backup = “Spencer Pennington”>

<!---set ‘stQuarterbacks’ value in stTide2002 using function StructInsert()--->

<cfset StructInsert(stTide2003,”stQuarterbacks”,stQuarterbacks)>

<!---set ‘Projected Record’ value to 11-2 using inline method --->

<cfset stTide2003[“Projected Record”] = “11-2”>

<!---cfset --->

<cfoutput>

<!---display ‘Coach’ value using inline method--->

2003 Coach: #stTide2003[“Coach”]#<br>

<!---display ‘Projected Record’ value using function StructFind()--->

2003 Projected Record: #StructFind(stTide2003,”Projected Record”)#<br>

<!---display ‘stQuarterback’ value using dot notation--->

2003 Quarterbacks: #StructCount(stTide2003.stQuarterbacks)#<br>

<ul>

<li>Starter: #stTide2003.stQuarterbacks.starter#</li>

<li>Backup: #StructFind(stTide2003.stQuarterbacks,”backup”)#</li>

</ul>

</cfoutput>

CommentsDot notation is the means of referring to a value by using the syntaxstructureName.keyName (if you are familiar with object oriented programming con-cepts, you probably recognize dot notation from object/property relationships).Thetechnique in this section shows examples of all three ways to insert values into andretrieve values from a structure, including using dot notation.

If you’ve programmed in ColdFusion before, chances are you’ve been using dot nota-tion to reference session variables, URL variables, form variables, or other values fromCFMX variable scopes. Remember—all named variable scopes in CFMX are available asstructures, so everything you learn in this chapter not only pertains to structures youbuild for your own purposes, but also to the CFMX named scopes.

06 0672324628 CH04 6/8/05 11:07 AM Page 58

Page 82: ColdFusion MX Developer's Cookbook (Developer's Library)

The technique in this section also takes advantage of populating structure elements withother structures (this was covered earlier in the chapter). Note that to refer to elementsof sub-structures, you simply provide the path to the parent structure and use your func-tion or dot notation as usual.

4.8. Looping Over a StructureYou want to iterate over the key/value pairs within a structure.

TechniqueUse StructKeyList() and cfloop to iterate over the elements in a structure.

<!---create stGreatTidePlayers structure--->

<cfset stGreatTidePlayers = StructNew()>

<!---populate stGreatTidePlayers structure as an associative array--->

<cfset stGreatTidePlayers[“Joe Namath”] = “Quarterback”>

<cfset stGreatTidePlayers[“Lee Roy Jordan”] = “Linebacker”>

<cfset stGreatTidePlayers[“Derrick Thomas”] = “Linebacker”>

<cfset stGreatTidePlayers[“Shuan Alexander”] = “Running Back”>

<cfset stGreatTidePlayers[“Johnny Musso”] = “Halfback”>

<!---present stGreatTidePlayers to browser--->

Famous Crimson Tide Football Players<br>

<table border=”1” cellpadding=”5”>

<tr>

<td width=”50%”>

<b>Player Name</b>

</td>

<td width=”50%”>

<b>Position</b>

</td>

</tr>

<cfoutput>

<!---use StructKeyList() to loop over keys in stGreatTidePlayers--->

<cfloop list=”#StructKeyList(stGreatTidePlayers)#” index=”i”>

<tr>

<!---display i, which is the current key--->

<td>#i#</td>

<!---use i to find the value stored in appropriate element--->

<td>#StructFind(stGreatTidePlayers,i)#</td>

</tr>

</cfloop>

</cfoutput>

</table>

594.8. Looping Over a Structure

06 0672324628 CH04 6/8/05 11:07 AM Page 59

Page 83: ColdFusion MX Developer's Cookbook (Developer's Library)

60 Chapter 4 Structures

CommentsOne of the more common tasks in dealing with structures is to loop over the structureto manipulate its elements. One important point to remember is that, because there is noorder to elements in a structure, there is no way to predict the order in which the ele-ments will appear in a loop.

The technique in this section defines a structure that provides some information ofjust a few of the greatest Crimson Tide football players.You build the associative array bystoring a player name in the key portion of the element and the position they played inthe value portion.

This example uses an associative array rather than a traditional structure.A traditionalstructure follows the object/property design defined earlier in the chapter.An associativearray, by contrast, stores values in both the key and the value portion of a structure ele-ment.

To iterate over the stGreatTidePlayers structure, you use theStructKeyList() function and loop over the returned list of keys. Each iteration ofthe list provides the current list item as an index, and you can use the current list item toreference the value of each element, because you know the item will be a key into thestructure.

Another way to loop over the structure is to pass the structure into the collectionargument of cfloop.The technique code produces the same output should you changethe cfloop line to read:

<cfloop collection=”#stGreatTidePlayers#” item=”i”>

Notice that you use StructFind() instead of dot notation to reference the valuestored in each element of the stGreatTidePlayers structure.This is because the keyportion of the element, in this case, contains a space (Lee Roy Jordan). Be careful ifyou don’t know if the value of a key is valid within the dot notation syntax. CFMX willthrow a ParseException exception when attempting to reference those keys.

4.9. Using Structure Utility FunctionsYou want to manipulate a structure using ColdFusion structure utility functions.

TechniqueUse structure utility functions to manipulate the contents of a structure.

<cfset cgiKeys = structKeyList(cgi)>

CommentsStructKeyList() is one of six CFMX structure utility functions.Table 4.4 defines allsix of these functions and describes their functionalities.

06 0672324628 CH04 6/8/05 11:07 AM Page 60

Page 84: ColdFusion MX Developer's Cookbook (Developer's Library)

614.10. Copying Structures

Table 4.4 CFMX Structure Utility Functions

Function Functionality

Duplicate(structure) Returns an exact copy of structure.All items arecopied by value.

StructFindKey(structure, Searches structure and its sub-collections for a keysearchString [,searchScope]) matching searchString. Returns an array of struc-

tures for each one found. Structure contains the ele-ments owner, value, and path. If searchScope is setto all, all matching items are returned. IfsearchScope is set to one, only one item isreturned.The default searchScope is one.

StructFindValue() Searches structure and its sub-collections for avalue matching searchString. Returns an array ofstructures for each one found. Structure contains theelements owner, key, and path. If searchScope is setto all, all matching items are returned. IfsearchScope is set to one, only one item isreturned.The default searchScope is one.

StructGet(structurePath) Returns the item found in string structurePath. Ifno structure is found using structurePath, anempty one is created in structurePath andreturned.

StructKeyArray() Returns an array of keys found in structure.Theorder is unpredictable as structures do not imposeorder on their elements.

StructKeyList(structure Returns a list of keys found in structure.[,delimiter]) Delimiter is a comma by default unless otherwise

specified.

The CFMX structure utility functions manipulate structures inside your application.Remember that all named variable scopes are provided as structures in CFMX, makingthese utility functions powerful when dealing with session, URL, form, and other scopes.

4.10. Copying StructuresYou want to copy the contents (deep or shallow) of a structure to anotherstructure.

TechniqueUse Duplicate() to perform a deep copy of a structure. Use StructCopy() to per-form a shallow copy.

06 0672324628 CH04 6/8/05 11:07 AM Page 61

Page 85: ColdFusion MX Developer's Cookbook (Developer's Library)

62 Chapter 4 Structures

<!---create stBamaTradition structure--->

<cfset stBamaTradition = StructNew()>

<cfset StructInsert(stBamaTradition,”SECChampionships”,”21”)>

<!---create stNationalChampionships structure as an element of stBamaTradition--->

<cfset stBamaTradition.stNationalChampionships.actual = “12”>

<!---some lesser schools dispute the actual number of Bama Championships--->

<cfset stBamaTradition.stNationalChampionships.claimedByRivals = “8”>

<!---perform a deep copy and a shallow copy of stBamaTradition structure

using Duplicate() and StructCopy()--->

<cfset stDeepCopyBamaTradition = Duplicate(stBamatradition)>

<cfset stShallowCopyBamaTradition = StructCopy(stBamatradition)>

<!---Bama wins an SEC and a National Championship in 2004--->

<cfset StructUpdate(stBamaTradition,”SECChampionships”,”22”)>

<cfsetStructUpdate(stBamaTradition.stNationalChampionships,”claimedByRivals”,”9”)>

<cfset StructUpdate(stBamaTradition.stNationalChampionships,”actual”,”13”)>

<cfoutput>

<!---display information stored in stBamaTradition structure--->

<b>stBamaTradition - original structure</b><br>

SEC Championships: #stBamaTradition.SECChampionships#<br>

National Championships

claimed by rivals:#stBamaTradition.stNationalChampionships.claimedByRivals#<br>

National Championships actual:#stBamaTradition.stNationalChampionships.actual#<br>

<p>

<!---display information stored in stDeepCopyBamaTradition structure--->

<b>stDeepCopyBamaTradition - created using Duplicate()</b><br>

SEC Championships: #stDeepCopyBamaTradition.SECChampionships#<br>

National Championships

claimed by rivals:#stDeepCopyBamaTradition.stNationalChampionships.claimedByRivals#<br>

National Championships

actual: #stDeepCopyBamaTradition.stNationalChampionships.actual#<br>

<p>

<!---display information stored in stSshallowCopyBamaTradition structure--->

<b>stShallowCopyBamaTradition - created using StructCopy()</b><br>

SEC Championships: #stShallowCopyBamaTradition.SECChampionships#<br>

National Championships claimed by rivals:

#stShallowCopyBamaTradition.stNationalChampionships.claimedByRivals#<br>

National Championships

actual: #stShallowCopyBamaTradition.stNationalChampionships.actual#<br>

</cfoutput>

CommentsA deep copy copies all items, including sub-elements, by value. It returns an exact dupli-cate of the target structure.A shallow copy copies all items in the first dimension by valueand all sub-elements by reference.

06 0672324628 CH04 6/8/05 11:07 AM Page 62

Page 86: ColdFusion MX Developer's Cookbook (Developer's Library)

Notice the output of the previous technique code.You created a first dimension ele-ment named SECChampionships.Then you performed both a deep copy and a shal-low copy on the stBamaTradition structure before changing the value ofSECChampionships. Notice the only structure that contains the updated value is theoriginal stBamaTradition structure.This is because both the deep copy and shallowcopy return the first dimension elements by value.

The difference is in the items beneath the first dimension.ThestNationalChampionships structure created to provide information about the Tide’snumerous championship years is copied by value into stDeepCopyBamaTraditionusing the Duplicate() function and copied by reference intostShallowCopyBamaTradition using the StructUpdate() function.This meansthat any changes to the stNationalChampionships structure will not appear in thestDeepCopyBamaTradition.After you update the values to reflect 2004 as a champi-onship year, stDeepCopyBamaTradition still contains the value 12 for its actual key.stShallowCopyBamaTradition, however, contains the new correct value (13)because it does not contain a structure named stNationalChampionships. It insteadcontains a reference to the stNationalChampionships structure instBamaTradition.

4.11. Sorting StructuresYou want to sort a structure.

TechniqueUse StructSort() to sort values in a structure.

<!---create and populate stTotalChampionships structure--->

<cfset stTotalChampionships = StructNew()>

<cfset structInsert(stTotalChampionships,”Nebraska”,”5”)>

<cfset structInsert(stTotalChampionships,”Oklahoma”,”7”)>

<cfset structInsert(stTotalChampionships,”Notre Dame”,”9”)>

<cfset structInsert(stTotalChampionships,”Alabama”,”7”)>

<cfset structInsert(stTotalChampionships,”Ohio State”,”6”)>

<!---sort structure based on number of championships,

set return array to aTCArray--->

<cfset aTCArray = StructSort(stTotalChampionships,”numeric”,”desc”)>

<cfoutput>

<table cellpadding=”5”>

<tr>

<td><b>School</b></td>

<td><b>Championships</b></td>

</tr>

<cfloop list=”#ArrayToList(aTCArray)#” index=”i”>

634.11. Sorting Structures

06 0672324628 CH04 6/8/05 11:07 AM Page 63

Page 87: ColdFusion MX Developer's Cookbook (Developer's Library)

64 Chapter 4 Structures

<tr>

<!---display school Name--->

<td>#i#</td>

<!---retrieve element from structure and display value--->

<td>#stTotalChampionships[i]#</td>

</tr>

</cfloop>

</table>

</cfoutput>

CommentsThe first rule of structures is that there is no order to their elements. It is obviously nec-essary for CFMX to provide programmers with a way to sort data stored in a structure.The StructSort() function enables you to do just that.StructSort() returns a sorted array of keys from the structure you provide to thefunction. It does not perform any action on the structure itself, so executingStructSort() does not change the elements of the structure in any way. It’s impossibleto sort an object without order, right? StructSort() accepts one required and three optional arguments.These arguments arepresented in Table 4.5.

Table 4.5 StructSort()’s Arguments

Argument Description

Structure The structure containing the keys you want returned sorted inspecified order.

sortType text, textnocase, or numeric. text sorts with case sensitivity—lowercase values are grouped apart from uppercase values. textnocase disregards case in values. numeric sorts valuesnumerically.The default is text.

sortOrder asc or desc. asc is for ascending sorts; desc is for descendingsorts.The default is asc.

structureReference The path to sub-element containing values required for the sort.Necessary for sorts based on sub-element values.

In the previous technique, the call to StructCopy() returned an array, which you setto the variable aTCArray.You then use the ArrayToList() function to create a listfrom the array values, which results in a sorted, comma-delimited list of keys for thestructure.

Now suppose you need to sort based on the value of a certain sub-element containedin the structure.The following code provides information about the four great coacheswho won national championships at Alabama.The keys of the first dimension of thestructure are the coaches’ names.The second dimension stores numerical data about the

06 0672324628 CH04 6/8/05 11:07 AM Page 64

Page 88: ColdFusion MX Developer's Cookbook (Developer's Library)

654.11. Sorting Structures

number of championships won and the most recent winning year for each coach. It thensorts the keys to the first dimension based on the values stored in the second.

<!---create championships structure--->

<cfset stChampionships = structNew()>

<!---build Wallace Wade--->

<cfset stWW = StructNew()>

<cfset stWW.count = “3”>

<cfset stWW.recent = “1930”>

<cfset stChampionships[“Wallace Wade”] = stWW>

<!---build Frank Thomas--->

<cfset stFT = StructNew()>

<cfset stFT.count = “2”>

<cfset stFT.recent = “1941”>

<cfset stChampionships[“Frank Thomas”] = stFT>

<!---build Paul Bryant--->

<cfset stPB = StructNew()>

<cfset stPB.count = “6”>

<cfset stPB.recent = “1979”>

<cfset stChampionships[“Paul ‘Bear’ Bryant”] = stPB>

<!---build Gene Stallings--->

<cfset stGS = StructNew()>

<cfset stGS.count = “1”>

<cfset stGS.recent = “1992”>

<cfset stChampionships[“Gene Stallings”] = stGS>

<cfoutput>

In order of most championships

<hr>

<table cellpadding=”5”>

<tr>

<td><b>Coach</b></td>

<td><b>Number of Championships Won</b></td>

</tr>

<!---build list from sorted structure--->

<cfset theCoachesList =

ArrayToList(StructSort(stChampionships, “numeric”, “DESC”, “count”))>

<cfloop list=”#theCoachesList#” index=”i”>

<tr>

<!---display coach name--->

<td>#i#</td>

<!---display count value--->

<td>#stChampionships[i].count#</td>

</tr>

</cfloop>

</table>

<p>

In order of most recent championship

06 0672324628 CH04 6/8/05 11:07 AM Page 65

Page 89: ColdFusion MX Developer's Cookbook (Developer's Library)

66 Chapter 4 Structures

<hr>

<table cellpadding=”5”>

<tr>

<td><b>Coach</b></td>

<td><b>Last Championship Won</b></td>

</tr>

<cfset theCoachesList =

ArrayToList(StructSort(stChampionships, “numeric”, “DESC”, “recent”))>

<cfloop list=”#theCoachesList#” index=”i”>

<tr>

<!---display coach name--->

<td>#i#</td>

<!---display recent value--->

<td>#stChampionships[i].recent#</td>

</tr>

</cfloop>

</table>

</cfoutput>

Remember that StructSort() returns an array of keys to the structure passed in thefirst argument.You need to reference the struct again to retrieve the value associatedwith that key.

06 0672324628 CH04 6/8/05 11:07 AM Page 66

Page 90: ColdFusion MX Developer's Cookbook (Developer's Library)

5Queries

5.0. IntroductionColdFusion’s capability to connect to a data source and retrieve data is possibly the mostwidely used functionality in the language. Most developers are familiar with the queryobject through its use in the process required to connect to and retrieve data from a datasource. In addition to the base query functionality, ColdFusion provides developers thecapability to do the following:

n Manually create query objects for use in Web applicationsn Query the recordset retrieved from a previous query (thus creating a query of

queries)n Manage the data contained within a query recordsetn Cache queries and limit the number of calls to the database

This chapter discusses and provides examples of all of these features and more.You’lllearn that the ColdFusion query object is a powerful, useful construct and can be used inmany ways.

5.1. Querying a DatabaseYou want to retrieve values from a database.

TechniqueUse the ColdFusion <cfquery> tag to connect to a database and return a recordset inthe form of a ColdFusion query object.

<!---query the cfcookbook database--->

<cfquery datasource=”cfcookbook” name=”qGetUsers”>

07 0672324628 CH05 6/8/05 11:07 AM Page 67

Page 91: ColdFusion MX Developer's Cookbook (Developer's Library)

68 Chapter 5 Queries

SELECT UserName, PassWord

FROM Users

</cfquery>

<cfoutput>

is qGetUsers a query object? #isQuery(qGetUsers)#

</cfoutput>

CommentsThis technique shows a simple query against the Users table of the cfcookbook datasource (the cfcookbook schema is defined in detail in Chapter 13,“User Authenticationand Authorization”). Executing this code example presents a simple YES to the users—the result of the isQuery() function call.

This code example uses only those parameters required to execute a query against adata source using the <cfquery> tag: the data source and name (if you are performing aquery of queries, as is discussed later in this chapter, the datasource parameter is notused).The ColdFusion <cfquery> tag accepts two required and nine optional parame-ters.Table 5.1 describes each of these parameters and describes their functions.

Table 5.1 cfquery Parameters

Parameter Function

Datasource Required. Name of the ColdFusion data source for the query.

Name Required. ColdFusion executes the query and returns a query object withthe name specified in this parameter.

blockFactor This parameter pertains only to Oracle data sources and defines the num-ber of records to return from the database at one time.

cachedAfter Must be a valid ColdFusion date value. If query caching is enabled in theColdFusion Administrator and this parameter value is less than the date ofthe original query, ColdFusion will return the cached recordset.

cachedWithin Must be a valid ColdFusion time span (created with CreateTimeSpan()function). If query caching is enabled in the ColdFusion Administrator andthe original query date falls within the specified time span, ColdFusion willreturn the cached recordset.

dbType Used in a query of queries to specify that the target dbType is a validColdFusion query object. Not used if the query target is a database.

Debug If debugging is enabled in the ColdFusion Administrator and DatabaseActivity is disabled, a value of true overrides the Database Activity setting.Also, omitting the equals sign and the true value implies true.

maxRows Maximum number of rows to return in the recordset.

Password Password for the data source.

Timeout Maximum time permitted to execute each operation performed in a query.Username Username of the data source.

07 0672324628 CH05 6/8/05 11:07 AM Page 68

Page 92: ColdFusion MX Developer's Cookbook (Developer's Library)

695.2. Programmatically Creating Queries

The following attributes of the <cfquery> tag are deprecated as of ColdFusion MX:connectString, dbName, dbServer, provider, providerDSN, and sql. Usingthem in a ColdFusion MX environment may cause errors or otherwise unexpectedresults.

NoteAs a best practice, all queries in this chapter begin with the letter q, as in qQueryName.

5.2. Programmatically Creating QueriesYou want to manually create a new query object.

TechniqueUse the QueryNew() function to programmatically create a ColdFusion query object.Use the QueryAddRow() and QuerySetCell() functions to programmatically addvalues to your query object.

<!---create a new query with two columns--->

<cfset qSimpleQuery = QueryNew("firstName, lastname")>

<!--- add a row to qSimpleQuery --->

<cfset newRow = QueryAddRow(qSimpleQuery)>

<!--- add values to the row just added--->

<cfset QuerySetCell(qSimpleQuery, "firstName", "Norman")>

<cfset QuerySetCell(qSimpleQuery, "lastName", "Saen")>

<!---add a column to the query--->

<cfset qAgeArray = ArrayNew(1)>

<cfset qAgeArray[1] = "12">

<cfset QueryAddColumn(qSimpleQuery, "age",qAgeArray)>

<!--- Display the values in qSimpleQuery --->

<cfoutput query="qSimpleQuery">

#firstName# #lastName#, #age# years old<br>

</cfoutput>

<cfoutput>Total Records: #qSimpleQuery.recordCount#</cfoutput>

CommentsThe capability to create ColdFusion query objects programmatically allows developers totake advantage of query-specific features, like the recordCount, currentRow, andcolumnList variables.As you’ll learn later in the chapter, a query object can also be thetarget of a <cfquery> execution—enabling you to create a query of a query.The steps to create a query object are as follows:

07 0672324628 CH05 6/8/05 11:07 AM Page 69

Page 93: ColdFusion MX Developer's Cookbook (Developer's Library)

70 Chapter 5 Queries

n Create the query object using the QueryNew() function.n Create one or more rows in the query object using the QueryAddRow()

function.n Add data to the query object using the QuerySetCell() function.

The QueryNew() function accepts a single required parameter, which is a list ofcolumns to create in the query object.The previous technique created a query objectnamed simpleQuery with the columns firstName and lastName. ColdFusionrequires a column list to create a new query, even if it is empty.

The QueryAddRow() function accepts one required and one optional parameter.Therequired parameter is the name of the query to which you need to add a row.The sec-ond and optional parameter is the integer number of rows you need to add. If you donot specify a number, the function adds only one.The example here shows only a singlerow and accepts the default value of 1.

Note that the QueryAddColumn() function accepts three parameters, all required.The first is the name of the query to which you need to add the column.The second isthe name of the new column.The third is an array of values.The values in the array arecopied to the new column in the query in the order in which they appear in the array. Ifthe query contains more rows than the array, the query will pad the column with emptyvalues.

5.3. Displaying Query ResultsYou want to display the results of a query in a Web page.

TechniqueDisplay the values stored in a query using <cfoutput>, <cfloop>, or by explicit refer-ence.

<!---create presidents query object--->

<cfset qPresidents = QueryNew(“firstName, lastname”)>

<!--- add 2 rows to qPresidents --->

<cfset newRow = QueryAddRow(qPresidents,2)>

<!--- populate the rows just added--->

<cfset QuerySetCell(qPresidents, “firstName”, “George”,1)>

<cfset QuerySetCell(qPresidents, “lastName”, “Washington”,1)>

<cfset QuerySetCell(qPresidents, “firstName”, “John”,2)>

<cfset QuerySetCell(qPresidents, “lastName”, “Adams”,2)>

<!--- Display the values in qPresidents using cfoutput--->

<b>Use cfoutput to display query values:</b><br>

<cfoutput query=”qPresidents”>

#firstName# #lastName#<br>

</cfoutput>

07 0672324628 CH05 6/8/05 11:07 AM Page 70

Page 94: ColdFusion MX Developer's Cookbook (Developer's Library)

715.4. Using Query Variables

<p>

<!--- Display the values in qPresidents using cfloop--->

<b>Use cfloop to display query values:</b><br>

<cfoutput>

<cfloop query=”qPresidents”>

#firstName# #lastName#<br>

</cfloop>

</cfoutput>

<p>

<!--- Display the values in qPresidents using an explicit reference--->

<b>Use an explicit reference to display query values:</b><br>

<cfoutput>

<cfloop from=”1” to=”#qPresidents.recordCount#” index=”i”>

#qPresidents.firstName[i]# #qPresidents.lastName[i]#<br>

</cfloop>

</cfoutput>

CommentsThis technique shows an example of each of the three ways to display the values storedin a query object—by using <cfoutput>, by using <cfloop>, and by explicitly refer-encing the value by column and row index.

To use <cfoutput>, you must pass the name of the query into the query attributeof the <cfoutput> tag. Doing so causes the CFML inside the <cfoutput> to executeonce for every record in the query, much like the behavior of a <cfloop> statement.

Using <cfloop> with the query attribute is very similar to using <cfoutput>with the query attribute.The only difference is that there is no <cfoutput>. If youwant to evaluate ColdFusion variables within the loop, you need to make sure yourstatements are contained within <cfoutput> tags.

The third way to display the values stored in a query is to do so by explicitly refer-encing the value by column and by row index.The syntax isqueryName.columnName[rowIndex], where queryName is the name of your query,columnName is the name of the column containing the variable you need to display, androwIndex is the cardinal-based index of the row containing the value you need to dis-play.

5.4. Using Query VariablesYou want to inspect a query using ColdFusion query variables.

TechniqueColdFusion provides a number of variables along with the query scope to help you bet-ter understand the object. Reference the variables like you do variables of any scope toinspect their values.

07 0672324628 CH05 6/8/05 11:07 AM Page 71

Page 95: ColdFusion MX Developer's Cookbook (Developer's Library)

72 Chapter 5 Queries

<!---query the cfcookbook database--->

<cfquery datasource=”cfcookbook” name=”qGetUsers”>

SELECT UserName, PassWord

FROM Users

</cfquery>

<!---display information about the query--->

<b>Query Information</b>

<hr>

<cfoutput>

record count: #qGetUsers.recordCount#<br>

column list: #qGetUsers.columnList#<br>

current row: #qGetUsers.currentRow#<br>

execution time: #cfquery.executionTime#

</cfoutput>

CommentsThe four ColdFusion Query Variables are recordCount, columnList, currentRow,and executionTime, and they are described as follows:

n recordCount provides the integer number of total records available in a query.n columnList provides the list of column names present in the query. Note that

the column names returned in the variable columnList are in alphabetical orderrather than in the order provided in the SQL statement.

n currentRow provides the index of the current row.This is especially useful whenexecuting cfloop statements.

n executionTime provides the cumulative number of seconds spent processing thequery. Note that the syntax for retrieving the executionTime value iscfquery.executionTime rather than queryName.executionTime.

The following code shows an example of inspecting the value of currentRow to inter-lace the background colors of the rows in a table. It uses columnList to display columnheadings and to retrieve query values. It also shows the query execution time and thetotal number of rows contained in the query.

<!---query the cfcookbook database--->

<cfquery datasource=”cfcookbook” name=”qGetUsers”>

SELECT FirstName, LastName, City, State

FROM Users

</cfquery>

<table cellpadding=”3”>

<cfoutput>

<tr>

<td colspan=”#listLen(qGetUsers.columnList)#”>

<b>User Information</b>

</td>

07 0672324628 CH05 6/8/05 11:07 AM Page 72

Page 96: ColdFusion MX Developer's Cookbook (Developer's Library)

735.5. Creating Queries of Queries

</tr>

<tr>

<!---display the column names--->

<cfloop list=”#qGetUsers.columnList#” index=”i”>

<td bgcolor=”silver”>

<font color=”white”><b>#i#</b></font>

</td>

</cfloop>

</tr>

<cfloop query=”qGetUsers”>

<!---interlace the background colors--->

<tr bgcolor=”#iif(currentRow MOD 2,de(“f1f1f1”),de(“ffffff”))#”>

<!---display the values--->

<cfloop list=”#qGetUsers.columnList#” index=”i”>

<td>

#evaluate(i)#

</td>

</cfloop>

</tr>

</cfloop>

<tr

<td colspan=”#listLen(qGetUsers.columnList)#”>

Total Records: #qGetUsers.recordCount<br>

Execution Time: #cfquery.executionTime#

</td>

</tr>

</cfoutput>

</table>

5.5. Creating Queries of QueriesYou want to perform SQL operations on an existing ColdFusion query.

TechniqueUse <cfquery> to query an existing query object rather than a database. Pass in a valueof query for the dbType parameter and the name of the existing query object for thedatasource parameter.

<!---query the cfcookbook database--->

<cfquery datasource=”cfcookbook” name=”qGetUsers”>

SELECT FirstName, LastName, City, State

FROM Users

</cfquery>

<!---query the qGetUsers query for people with state equal to NC--->

07 0672324628 CH05 6/8/05 11:07 AM Page 73

Page 97: ColdFusion MX Developer's Cookbook (Developer's Library)

74 Chapter 5 Queries

<cfquery dbType=”query” name=”qGetNCUsers”>

SELECT FirstName, LastName

FROM qGetUsers

WHERE State = ‘NC’

</cfquery>

<b>NC users</b>

<hr>

<cfoutput query=”qGetNCUsers”>

#qGetNCUsers.FirstName# #qGetNCUsers.LastName#<br>

</cfoutput>

<p>

<!---query the qGetUsers query for people with state not equal to NC--->

<cfquery dbType=”query” name=”qGetOtherUsers”>

SELECT FirstName, LastName

FROM qGetUsers

WHERE State <> ‘NC’

</cfquery>

<b>Other users</b>

<hr>

<cfoutput query=”qGetOtherUsers”>

#qGetOtherUsers.FirstName# #qGetOtherUsers.LastName#<br>

</cfoutput>

CommentsThe query of queries (sometimes called an in-memory query) is a powerful ColdFusionfeature. It can significantly improve performance if you find the need to select data fromthe same table more than once. Using a query of queries, you need only a single call tothe database, as shown in the previous technique.

Executing a <cfquery> call returns a dataset, which in many ways is similar to adatabase table—a recordset contains data structured as a virtual table with rows andnamed columns.This similarity is exploited in the query of queries’ functionality.ColdFusion treats the recordset as a database table against which you can execute SQLstatements to retrieve data.

Without a query of queries, the technique code would require two database calls toextract two separate recordsets with the desired data—one to retrieve users from NCand one to retrieve users not from NC. By using a query of queries, you can pull all theusers in one database call and then query the returned recordset using the appropriateWHERE clauses.

A query of queries is also beneficial in conjunction with cached queries.You can dis-play the results of a single cached query in any number of ways across multiple templatesusing the cached recordset as a virtual table.

Note also that you are not limited to database-returned recordsets when using aquery of queries.You can use any valid ColdFusion recordset as the input.The result of a <cfdirectory> call, for example, is valid for input into a query of queries.

07 0672324628 CH05 6/8/05 11:07 AM Page 74

Page 98: ColdFusion MX Developer's Cookbook (Developer's Library)

5.6. Converting a Query Column to a ListYou want to extract all query values for a specific column and store them in a list.

TechniqueUse the ValueList() or QuotedValueList() functions to return a list of all valuesstored in a specific query column.

<!---query the cfcookbook database--->

<cfquery datasource=”cfcookbook” name=”qGetUsers”>

SELECT FirstName

FROM Users

</cfquery>

<!---display a list of all the values in column UserName--->

<b>All UserNames</b>

<hr>

<cfoutput>#ValueList(qGetUsers.FirstName)#</cfoutput>

<p>

<!---use quoted value list as IN clause in a new query--->

<cfquery datasource=”cfcookbook” name=”qGetEmployees”>

SELECT Name

FROM Employees

Where Name IN (#quotedValueList(qGetUsers.FirstName)#)

</cfquery>

<!---display Employees who share a first name with Users--->

<b>Shared First Names</b>

<hr>

<cfoutput query=”qGetEmployees”>

#Name#<br>

</cfoutput>

CommentsThe ValueList() and QuotedValueList() functions are used to create a list from aspecific column in a query.

ValueList() accepts one required and one optional argument.The required argu-ment is the name of the query you need to transform into a list object.The optionalargument is the delimiter to use for the list. If you do not provide a delimiter, a commais used as the default.

QuotedValueList() also creates a list from a query column but qualifies the valueswith single quotes.The function otherwise behaves exactly like ValueList(), with thesame required and optional arguments.

755.6. Converting a Query Column to a List

07 0672324628 CH05 6/8/05 11:07 AM Page 75

Page 99: ColdFusion MX Developer's Cookbook (Developer's Library)

76 Chapter 5 Queries

QuotedValueList() is especially useful in conjunction with a query—you can use thequoted list as the IN clause of a SQL statement, as is shown in the previous technique.For more information on ColdFusion lists, see Chapter 2,“Working with Lists.”

5.7. Caching a QueryYou want to use the cached result of a previous <cfquery> execution.

TechniqueUse the cachedAfter or cachedWithin parameters of <cfquery> to use cachedresults if they exist.

<!---query cfcookbook for all users--->

<!---use cached results if query executed since yesterday--->

<cfquery

datasource=”cfcookbook”

name=”qGetUsersA”

cachedAfter=”#DateFormat(Now()-1)#”>

SELECT FirstName, LastName, City, State

FROM Users

ORDER BY LastName

</cfquery>

<!---display results--->

<b>Users</b>

<hr>

<cfoutput query=”qGetUsersA”>

#LastName#, #FirstName# - #City#, #State#<br>

</cfoutput>

<!---execution time should be 0 if cache is used--->

<cfoutput>

Execution Time: #cfquery.ExecutionTime#

</cfoutput>

<p>

<!---use cached results if query executed within the last 2 minutes--->

<cfquery

datasource=”cfcookbook”

name=”qGetUsersB”

cachedWithin=”#CreateTimeSpan(0, 0, 2, 0)#”>

SELECT FirstName, LastName, City, State

FROM Users

ORDER BY LastName

</cfquery>

<!---display results--->

<b>Users</b>

07 0672324628 CH05 6/8/05 11:07 AM Page 76

Page 100: ColdFusion MX Developer's Cookbook (Developer's Library)

775.7. Caching a Query

<hr>

<cfoutput query=”qGetUsersB”>

#LastName#, #FirstName# - #City#, #State#<br>

</cfoutput>

<!---execution time should be 0 if cache is used--->

<cfoutput>

Execution Time: #cfquery.ExecutionTime#

</cfoutput>

CommentsQuery caching is a great tool for improving Web application performance.The fewer thenumber of calls you make to the database, the faster your application.

You can control the number of queries ColdFusion will cache by changing thedefault setting. Up to 100 queries are cached by default.The stack will eliminate theoldest query if the threshold is reached.

In order to use a cached query, the following stipulations must be met:n Both queries must have the same name valuen Both queries must have the same datasource valuen Both queries must use the same SQL statementn Both queries must have the same username, if applicablen Both queries must have the same password, if applicablen The cached query must have been executed within the supplied time span ifcachedWithin parameter is provided

n The cached query must have been executed since the supplied date if thecachedAfter parameter is provided

The technique code shows an example of using cached queries with cachedAfter andcachedWithin.The first execution of the technique code should show a value for theexecution time for both queries.An immediate refresh of the page will show the samedata, but with execution times of 0, because ColdFusion used the cached query resultsrather than executing a new call to the database.

07 0672324628 CH05 6/8/05 11:07 AM Page 77

Page 101: ColdFusion MX Developer's Cookbook (Developer's Library)

07 0672324628 CH05 6/8/05 11:07 AM Page 78

Page 102: ColdFusion MX Developer's Cookbook (Developer's Library)

6Dates and Times

6.0. IntroductionA date is a data type that represents an instant.A date is really both a date and a time—all date objects represent both values. ColdFusion dates are accurate to the nearest second.

Dates can be formatted in a number of ways.The same date object can be formattedas a date string, such as “05/16/67” in one case, and then formatted as a time, such as“7:08 a.m.”, in another. It is up to the developer to determine how a date should berendered.There are some standard formats (called masks) that can help you present a datein the appropriate format. In one instance you may simply display a date as a string. Inanother, you may need to format the date as an ODBC date for a database query. Inanother case, the date may need formatting as an HTTP time string for setting cookieexpiration.

This chapter explores ColdFusion date/time support, including creating, formatting,displaying, and performing computations on date and time objects.

6.1. Creating a Date,Time, or DateTime Object

You want to create a ColdFusion Date, Time, or DateTime object.

TechniqueUse the appropriate ColdFusion date and time create function to create a ColdFusionDate, Time, or DateTime object.

<cfset mycreatedate = CreateDate(2002, 5, 22)>

<cfset mycreatetime = CreateTime(8, 12, 30)>

<cfset mycreatedatetime = CreateDateTime(2002, 5, 22, 8, 12, 30)>

08 0672324628 CH06 6/8/05 11:07 AM Page 79

Page 103: ColdFusion MX Developer's Cookbook (Developer's Library)

CommentsThis technique is a simple example of creating three date objects representing a Date, aTime, and a DateTime.These date objects can now be used in any ColdFusion func-tions that expect a date object as a parameter.

The parameters passed to each function used in the technique are presented in Table 6.1.

Table 6.1 Date and Time Create Parameters

Function Parameters

CreateDate(year,month,day) year (0-9999),month (1-12),day (1-31).Note the time portion of the returned date objectis set to 00:00:00.

CreateTime(hour,minute,second) hour (0-23), minute (0-59), second

(0-59). Note that the date portion of the returneddate object is set to 1899-12-30 (December 30,1899).

CreateDateTime year (0-9999),month (1-12),day (1-31),

hour (0-23), minute (0-59), second

(0-59).

Notice that when you output the values created in the technique without a mask, thedisplay is a timestamp—essentially unreadable unless your users are expecting it.The fol-lowing code shows the result of displaying the three date objects created as raw dateobjects, without using a formatting mask.

mycreatedate = {ts ‘2002-05-22 00:00:00’}

mycreatetime = {ts ‘1899-12-30 08:12:30’}

mycreatedatetime = {ts ‘2002-05-22 08:12:30’}

So the primary use of these create functions is to create a date object representing apoint in time.These functions are not for display purposes.

6.2. Formatting DatesYou want to format a date for user-friendly display.

TechniqueUse the ColdFusionDateFormat() function with the appropriate mask to format adate object for display.

<cfoutput>#DateFormat(CreateDate(2002,11,17),”mmmm d, yyyy”)#</cfoutput>

80 Chapter 6 Dates and Times

08 0672324628 CH06 6/8/05 11:07 AM Page 80

Page 104: ColdFusion MX Developer's Cookbook (Developer's Library)

816.2. Formatting Dates

CommentsThe DateFormat() function is essential when using ColdFusion date objects.DateFormat() accepts two parameters: the date object (or string representation of one)to be formatted and the mask with which to format that date object.The mask parame-ter is a string representing the format to display.Table 6.2 describes available characters tocreate masks.

Table 6.2 DateFormat Mask Values

Date Part Character Masks and Examples(formatting September 05,2002 6:06:05 PM)

Year y: 2

yy: 02

yyyy: 2002

Month m: 9

mm: 09

mmm: Sep

mmmm: September

Day d: 5

dd: 05

ddd: Sun

dddd: Sunday

Hour h: 6

hh: 06

H: 18

HH: 18

Minute m: 6

mm: 06

Second s: 5

ss: 05

AM / PM suffix t: Ptt: PM

ColdFusion also supplies preformatted masks to display date values.These are listed inTable 6.3.

08 0672324628 CH06 6/8/05 11:07 AM Page 81

Page 105: ColdFusion MX Developer's Cookbook (Developer's Library)

82 Chapter 6 Dates and Times

Table 6.3 DateFormat Mask Values

Mask Name Example

short 11/17/02

medium Nov 17, 2002

long November 17, 2002full Sunday, November 17, 2002

To display today’s date, use the ColdFusion function Now() as the date parameter for theDateFormat() function. Now() returns a date object representing the present momentin time, from the current year to the current second.The following example usesDateFormat() to place different formatting masks on the returned value of Now().Run this code on your machine and notice the different displays.

<cfoutput>

<table border=”1”>

<tr>

<th>Mask</th>

<th>Result</th>

</tr>

<tr>

<td>”full”</td>

<td>#DateFormat(Now(),”full”)#</td>

</tr>

<tr>

<td>”mm - dd - yy”</td>

<td>#DateFormat(Now(),”mm - dd - yy”)#</td>

</tr>

<tr>

<td>”d mmm”</td>

<td>#DateFormat(Now(),”d mmm”)#</td>

</tr>

</table>

</cfoutput>

6.3. Comparing DatesYou want to determine whether a date is greater than, less than, or equal toanother date.

TechniqueUse the ColdFusion DateCompare() function to compare two date objects.

08 0672324628 CH06 6/8/05 11:07 AM Page 82

Page 106: ColdFusion MX Developer's Cookbook (Developer's Library)

<cfset birthday = CreateDateTime(1975,9,22,9,7,0)>

<cfoutput>

#DateCompare(Now(),birthday)#

</cfoutput>

CommentsThe ColdFusion DateCompare() function accepts two required parameters and oneoptional parameter.The two required parameters are date objects, whereas the optionalparameter is the precision you want to use for the comparison.

DateCompare() returns one of three values: –1, 0, or 1.A –1 return value means thefirst date parameter is less than the second.A 0 return value means the two dates areidentical.A 1 return value means the first date parameter is greater than the second.Executing the code in the previous technique will return a 1 because the date returnedfrom the call to the Now() function is greater than the date value for the variable namedbirthday.

You can also alter the precision with which DateCompare() compares two dates byproviding a third parameter.This third parameter is the shorthand value for the date partyou want to compare—instructing DateCompare() to be precise only to the supplieddate part.Table 6.4 describes the values acceptable for this precision parameter.

Table 6.4 DateCompare Precision Values

Precision Value Description

yyyy Year

m Month

d Day

h Hour

n Minutes Second

Altering the precision used in DateCompare() is useful for comparing two date objectswhen, for example, you only need to know that they represent dates within the sameminute or within the same hour.

6.4. Determining Date DifferencesYou want to determine the difference in time between two date objects.

TechniqueUse the ColdFusion DateDiff() function to determine the difference in time betweentwo date objects.

836.4. Determining Date Differences

08 0672324628 CH06 6/8/05 11:07 AM Page 83

Page 107: ColdFusion MX Developer's Cookbook (Developer's Library)

84 Chapter 6 Dates and Times

<cfset birthday = CreateDateTime(1975,9,22,9,7,0)>

<cfoutput>

#DateDiff(“s”,birthday,Now())#

</cfoutput>

CommentsThe ColdFusion function DateDiff() compares two dates and returns the number ofselected date parts between the two.The previous technique returns the difference inseconds between the return value of the Now() function call and the value for the dateobject variable birthday. Executing this code displays a number value of nearly 800million.Table 6.5 describes the accepted values for the date part parameter.

Table 6.5 DateDiff Date Part Parameter Values

Date Part Value Description

s Second

n Minute

h Hour

w Week

ww Weekday

d Day

y Day of Year

m Month

q Quarteryyyy Year

6.5. Formatting TimesYou want to format a time for user-friendly display.

TechniqueUse the ColdFusion TimeFormat() function with the appropriate mask to format adate object for display.

<cfoutput>#TimeFormat(now(), “h:mm tt”)#</cfoutput>

CommentsUse the ColdFusion TimeFormat() function with the appropriate mask to format thetime portion of a date object for display. TimeFormat() accepts two parameters: the

08 0672324628 CH06 6/8/05 11:07 AM Page 84

Page 108: ColdFusion MX Developer's Cookbook (Developer's Library)

856.6. Defining Time Spans

date object (or a string representation of one) containing the time to be formatted andthe mask with which to format that time.The mask parameter is a string representingthe format to display.Table 6.6 describes available characters to create masks.

Table 6.6 TimeFormat Mask Values

Time Part Character Masks and Examples(formatting 6:05:04 PM Eastern Standard)

Hour h: 6

hh: 06

H: 18

HH: 18 (capital H used for 24 hour time)

Minute m: 5

mm: 05

Second s: 4

ss: 04

Suffix t: Ptt: PM

ColdFusion also supplies preformatted masks to display time values.These are listed inTable 6.7.

Table 6.7 TimeFormat Mask Values

Mask Name Example

Short 6:05 PM

Medium 6:05:04 AM

Long 6:05:04 PM EDTFull 6:05:04 PM EDT

6.6. Defining Time SpansYou want to define a date or time period.

TechniqueUse the ColdFusion function CreateTimeSpan() to define a date or time period.

<cfset myTimeSpan = #CreateTimeSpan(1, 12, 0, 0)#>

08 0672324628 CH06 6/8/05 11:07 AM Page 85

Page 109: ColdFusion MX Developer's Cookbook (Developer's Library)

86 Chapter 6 Dates and Times

CommentsThe CreateTimeSpan() function is useful in three ways. First, it is used as an attributevalue in the <cfapplication> tag for defining session and application timeout (seeChapter 7,“Application Flow,” for details on ColdFusion applications). Second, it used asan attribute in <cfquery> tags in conjunction with query caching to define the timeperiod for which a cached query is valid (see Chapter 5,“Queries,” for more detail onColdFusion queries).Third, it is used to subtract from or add to DateTime objects.

To add or subtract time to an existing date object, use CreateTimeSpan() and sim-ple arithmetic on an existing date. See the following code; it shows today’s, yesterday’s,and tomorrow’s date using only the Now() function and a time span object representinga 24-hour period.

<cfset today = Now()>

<cfset myTimeSpan = #CreateTimeSpan(0, 24, 0, 0)#>

<cfset yesterday = today - myTimeSpan>

<cfset tomorrow = today + myTimeSpan>

<cfoutput>

Today is #DateFormat(today,”dddd, mmmm d”)#<br>

Yesterday was #DateFormat(yesterday,”dddd, mmmm d”)#<br>

Tomorrow is #DateFormat(tomorrow,”dddd, mmmm d”)#

</cfoutput>

6.7. Using Date Information FunctionsYou want to inspect a date object for specific information.

TechniqueUse one of the many ColdFusion information functions to inspect a date object for spe-cific information.

<cfoutput>#isLeapYear(Year(Now()))#</cfoutput>

CommentsColdFusion provides a number of date information functions useful for inspecting datecontents and for extracting information from date objects and portions of date objects.The previous technique uses two of these said functions to determine whether the cur-rent year is a leap year. If you execute this code during a leap year, the code will displaya value of YES, otherwise it will display NO.

Table 6.8 lists the ColdFusion information functions and their return values.

08 0672324628 CH06 6/8/05 11:08 AM Page 86

Page 110: ColdFusion MX Developer's Cookbook (Developer's Library)

876.7. Using Date Information Functions

Table 6.8 ColdFusion Date Information Functions

Function Return Value

DayOfYear(dateObject) The numeric day of the year contained indateObject.

DaysInYear(dateObject) The number of days of the year contained indateObject.

FirstDayOfMonth(dateObject) The number relating the first day of the month indateObject to the beginning of the year contained indateObject.

DaysInMonth(dateObject) The number of days of the month contained indateObject.

MonthAsString(integer) Integer must be in the range 1-12. Returns themonth as a string corresponding to the supplied integer.

DayOfWeek(dateObject) The numeric day of the week contained indateObject. Sunday is a 1; Saturday a 7.

DayOfWeekAsString(integer) Integer must be in the range 1-7. Returns the day ofthe week as a string corresponding to the supplied integer.

IsLeapYear(integer) YES if year integer is a leap year; NO if it is not.

Year(dateObject) The year contained in dateObject.

Quarter(dateObject) The numeric quarter of the year contained indateObject (1-4).

Month(date) The numeric month contained in dateObject.January is a 1; December is a 12.

Week(dateObject) The number relating the week in dateObject to thebeginning of the year contained in dateObject.

Day(dateObject) The numeric day of the month contained indateObject.

Hour(dateObject) The numeric hour contained in dateObject, returnedas a 24-hour value.

Minute(dateObject) The numeric minute contained in dateObject.Second(dateObject) The numeric second contained in dateObject.

08 0672324628 CH06 6/8/05 11:08 AM Page 87

Page 111: ColdFusion MX Developer's Cookbook (Developer's Library)

88 Chapter 6 Dates and Times

6.8. Managing Dates and Times in Different Locales

You want to format ColdFusion date objects in a locale-specific manner.

TechniqueUse ColdFusion locale-specifc date functions to manage dates over different locales.

<cfoutput>

Format for Locale #GetLocale()# is: #LSDateFormat(Now(),”long”)#<br>

<cfset SetLocale(“Italian (Standard)”)>

Format for Italian (Standard) is: #LSDateFormat(Now(),”long”)#<br>

</cfoutput>

CommentsDates are closely linked to the locale. A locale setting tells ColdFusion which part of theworld is using the application. Learning to take advantage of locale settings is a powerfulskill for developers, especially in today’s’ 24-hour e-business environment. ColdFusion’sdefault locale is the same as the default local of the underlying Java Virtual Machine.Locales allow ColdFusion to format dates according to a variety of pre-defined loca-tions, so you don’t need to know the various formats of those locations.ColdFusion provides rich functionality for managing date objects in a locale-specificmanner. Executing the code in the previous technique will display the current time for-matted for your default locale. It then changes the default locale for your client (whichwill last the extent of your session) to Italian (Standard). Displaying the date, using thesame mask for the LSDateFormat() function, produces a new result—this time for-matted for the Italian (Standard) locale.

NoteColdFusion can manage dates as locale-specific as long as the locale needed is defined on the

ColdFusionMX Server. The Server.ColdFusion.SupportedLocales variable contains a comma-

delimited list of supported locales for the current server. Attempting to display date and time values in

locales not defined on the server generates a runtime critical CFLocaleMgrException exception.

There is also a similar formatting function for displaying time values per locale, calledLSTimeFormat(). Change the code in the previous technique to useLSTimeFormat() instead of LSDateFormat() to see the time formatted for differentlocales.

08 0672324628 CH06 6/8/05 11:08 AM Page 88

Page 112: ColdFusion MX Developer's Cookbook (Developer's Library)

IIControlling Application Flow

7 Application Flow

8 Exception Handling

09 0672324628 Part 02 6/8/05 11:08 AM Page 89

Page 113: ColdFusion MX Developer's Cookbook (Developer's Library)

09 0672324628 Part 02 6/8/05 11:08 AM Page 90

Page 114: ColdFusion MX Developer's Cookbook (Developer's Library)

7Application Flow

7.0. IntroductionA ColdFusion application is a group of ColdFusion templates associated to perform spe-cific functions. Most ColdFusion Web sites are ColdFusion applications.Anything from asimple form presentation and data-capture mechanism to a full-blown back officeintranet system can be considered a ColdFusion application.

A ColdFusion application consists of an Application.cfm page and shared variablescopes for the ColdFusion templates associated with the application.Applications allowtemplate access to the session scope, the client scope, and the application scope.

This chapter defines how to create and manage an application and also describes thevarious scopes available within an application.

7.1. Creating a ColdFusion ApplicationYou want to create a ColdFusion application.

TechniqueUse the <cfapplication> tag to create a ColdFusion application.<cfapplication

name=”myApplication”>

CommentsThe only requirement to create a ColdFusion application is the presence of the <cfapplication> tag.This tag is usually placed in a file named Application.cfmlocated in the root directory of your application.The Application.cfm file is usefulbecause if ColdFusion finds this file in the directory or any parent directories up to the

10 0672324628 CH07 6/8/05 11:08 AM Page 91

Page 115: ColdFusion MX Developer's Cookbook (Developer's Library)

92 Chapter 7 Application Flow

Web root, code inside the file will be executed before any logic in the requested page.For that reason, it’s typical to set global variables in what is called the application scope sothat they will always be available to the templates comprising the application.

The <cfapplication> tag allows you to associate ColdFusion templates for thepurposes of defining a ColdFusion application.There are no required attributes for the<cfapplication> tag, although there are numerous optional ones.Table 7.1 definesthese attributes and describes their purposes.

Table 7.1 cfapplication Optional Attributes

Attribute Description

applicationTimeout A timespan value that defines the lifetime of variables in the appli-cation scope.The default is set in the ColdFusion Administrator.

clientManagement Defines whether the client variable scope exists for the application.Accepted values are Yes and No. Default is No.

clientStorage If Client scope variables are used, this variable defines the storagemechanism for those values.Accepted values are cookie,registry, or the name of any valid ColdFusion data source con-figured to store client variables. Client storage is discussed in detaillater in this chapter. Default is registry.

name The string name of your ColdFusion application. If you choose touse the application or session variable scopes, this attribute isrequired.

sessionManagement Defines whether the session variable scope exists for the applica-tion.Accepted values are Yes and No. Default is No.

sessionTimeout A timespan value that defines the lifetime of variables in the sessionscope.The default is set in the ColdFusion Administrator.

setClientCookies Defines whether ColdFusion sends cookies to the client machinecontaining client identifiers for the application. Default is Yes.

setDomainCookies Sets domain-level client identifiers, used primarily for applicationsrunning in a clustered environment.Accepted values are Yes andNo. Default is No.

When ColdFusion executes any .CFM template, it will look up the directory tree forthe presence of an Application.cfm file and should it find one, it will execute thecode in that file before processing the requested template.The <cfapplication> tag isusually the first line of code in the Application.cfm file.The <cfapplication> tagis used to define the type of application the requested file belongs to.

NoteUsers are not allowed to browse directly to pages named Application.cfm. If they attempt to do so,

ColdFusion throws a ReservedTemplateException exception.

10 0672324628 CH07 6/8/05 11:08 AM Page 92

Page 116: ColdFusion MX Developer's Cookbook (Developer's Library)

937.1. Creating a ColdFusion Application

The applicationTimeout attribute defines the lifetime of variables in the applicationscope. If the application scope is used, the name attribute of the <cfapplication> tagis required.The value of the applicationTimeout attribute is a valid ColdFusiontimespan usually created with a call to the CreateTimeSpan() function. For more onthe CreateTimeSpan() function, see Chapter 6,“Dates and Times.”The following lineof code defines a ColdFusion application with an application scope lifetime of 2 daysand 12 hours:

<cfapplication

name=”myApplication”

applicationTimeout=”#CreateTimeSpan(2,12,0,0)#”>

You can also omit the applicationTimeout attribute, thereby accepting the defaultvalue for the parameter.The default for this value is a server-wide setting controlled bythe ColdFusion Administrator.To change this setting, log into your ColdFusionAdministrator and browse to the Memory Variables page. Note that from this page youcan also disable the use of the application variable scope, as well as define a maximumtimeout value.

If you need to use the client variable scope, you need to set the value forclientManagement to Yes and also define a storage mechanism for the client vari-ables.You also need to decide on a value for setClientCookies. If set to Yes,setClientCookies instructs ColdFusion to store the client identifier as a cookie onthe client machine. Note that users can reject acceptance for cookies, sosetClientCookies should be used with caution if your application is not used in acontrolled client environment. Storage strategies for client variables are discussed later inthe chapter.

Likewise, if you need to use the session variable scope, you need to set the value forsessionManagement to Yes.The ColdFusion administrator allows you the option tochoose ColdFusion Session Management or J2EE Session Management. If you useColdFusion Session Management, session variables use the same client identifier asColdFusion client variables (CFID and CFTOKEN) and are not available to any Java ServerPages (JSPs) or Java servlets you may access inside of your application. If you use J2EEsession management, your client identifier is available through a variable namedjSessionId and variables inside the session scope are made available to any JSPs youmay access inside of your application.

Client and session variable scopes effectively store information about a single clientinside a single application.The best practice is to use the session variable scope to storesingle-session specific variables and to use the client variable scope to store values thatyou need to access over a number of different client sessions. For example, a good placeto store shopping cart-related values is in the client scope, because you’ll likely want theapplication to recall the contents of a user’s shopping cart over a number of client sessions.

10 0672324628 CH07 6/8/05 11:08 AM Page 93

Page 117: ColdFusion MX Developer's Cookbook (Developer's Library)

94 Chapter 7 Application Flow

7.2. Using the Application Variable ScopeYou want to initialize application-wide settings and variables before each pagerequest.

TechniqueUse <cfset> and the application prefix inside Application.cfm to initialize variablesin the application scope.

<cfapplication

name=”myApplication”>

<cfset application.ds = “myDataSource”>

<cfset application.dsu = “dsUsername”>

<cfset application.dspw = “dsPassword”>

CommentsThis technique initializes three application scope variables to be executed before each.CFM page request. One common variable set in database-driven Web sites is the nameof the primary data source for the application. Using the code in the technique allowsdevelopers responsible for individual page development to access the primary databasewithout needing to know the name, username, or password necessary for access.Thisway, the developer responsible for managing the ColdFusion data source can change theusername or password, and even change the name of the DSN without worrying aboutseeking out each call to the database inside the application and changing the connectioninformation.Without setting the DSN name, username, and password in the applicationpage, each query to the database might look like:

<cfquery

datasource=”myDSN”

username=”username”

password=”password”>

Select ...

</cfquery>

But if the developer responsible for managing the entire ColdFusion application definesthe values for the DSN name, username, and password inside the application scope,developers responsible for individual template development can simply use the applica-tion variables for the necessary values, thereby allowing the global change of these valuesin a single setting, like so:

<cfquery

datasource=”#Application.ds#”

username=”#Application.dsu#”

password=”#Application.dspw#”>

Select ...

</cfquery>

10 0672324628 CH07 6/8/05 11:08 AM Page 94

Page 118: ColdFusion MX Developer's Cookbook (Developer's Library)

957.3. Implementing Session Management

7.3. Implementing Session ManagementYou want to use ColdFusion Session Management in your application.

TechniqueUse the session prefix to manage variables in the session scope.

<cfif not isDefined(“session.todaysDate”)>

<cfset session.todaysDate = Now()>

</cfif>

CommentsThis technique determines whether the session variable named todaysDate exists, andif it does not, creates it and sets it to the value returned from a call to the Now() func-tion. Now() returns a ColdFusion Datetime value equal to the current date and timeon the application server. For more information about the Now() function, refer back toChapter 6.

In order to use the session scope you need to first add the sessionManagementattribute to your <cfapplication> tag and set it to Yes.After you’ve done so, youcan manage variables stored in the session scope.

If you are using ColdFusion Session Management, an initial page request from a clientsets four variables immediately in the session scope for that user: CFID, CFTOKEN,sessionId, and urltoken.

NoteThe variables set by ColdFusion in the session scope are writable, just as the variables placed there by a

developer are. Changing the variables set by ColdFusion in the session scope can produce unexpected results

and is not recommended.

The session.CFID and session.CFTOKEN will be the same value as theclient.CFID and client.CFTOKEN if you are also using Client Management.Thesetwo variables represent the unique client identifier ColdFusion will use to retrieveclient-specific variables in the session and client scopes.The session.sessionId willbe a concatenated value of the application name, the CFID, and the CFTOKEN.The urltoken will be a URL-formatted value of the CFID and CFTOKEN. It is a good ideato pass this urltoken between page requests to ensure session integrity.The followingcode shows how to pass the CFID and CFTOKEN identifiers across URLs:

<cfoutput>

<a href=”someTemplate.cfm?#session.urltoken#”>link</a>

</cfoutput>

10 0672324628 CH07 6/8/05 11:08 AM Page 95

Page 119: ColdFusion MX Developer's Cookbook (Developer's Library)

96 Chapter 7 Application Flow

This code displays as the following link in the HTML sent to the client browser (ofcourse, the values for CFID and CFTOKEN are specific to each application and each user):

<a href=”someTemplate.cfm?CFID=1601&CFTOKEN=16915231”>link</a>

Passing this client identifier along with page requests allows ColdFusion to reference theindividual client’s session scope variables.

The session scope, like the application scope, is stored in memory on the applicationserver. For high load applications, Client Management with an optimized storage mecha-nism may be a better idea for storing client specific data.

NoteThe session scope should be used for values that you want to exist only for the current session. If you need

to set a variable whose lifetime should exist over multiple sessions, use the client scope instead.

7.4. Implementing Client ManagementYou want to use ColdFusion Client Management in your application.

TechniqueUse the client prefix to manage variables in the client scope.

<cfif not isDefined(“client.navigationPreference”)>

<cfset client.navigationPreference =

application.defaultNavigationPreference>

</cfif>

CommentsThis technique determines whether the client variable namednavigationPreference exists, and if it does not, creates it and sets it to the value forthe application variable defaultNavigationPreference.

In order to use the client scope, you first need to add the clientManagementattribute to your <cfapplication> tag and set it to Yes.You can also set theclientStorage value to define the storage mechanism for the client scope (clientscope storage is discussed later in this chapter).After you’ve done so, you can managevariables stored in the client scope.

An initial page request from a client immediately initializes six variables in the clientscope for that user: CFID, CFTOKEN, hitCount, lastVisit, timeCreated, and urltoken.

10 0672324628 CH07 6/8/05 11:08 AM Page 96

Page 120: ColdFusion MX Developer's Cookbook (Developer's Library)

977.5. Storing Client State Using the Registry

NoteThe variables set by ColdFusion in the client scope are writable, just as the variables placed there by a

developer are. Changing the variables set by ColdFusion in the client scope can produce unexpected results

and is not recommended.

The client.CFID and client.CFTOKEN will be the same value as thesession.CFID and session.CFTOKEN if you are also using Session Management.These two variables represent the unique client identifier that ColdFusion will use toretrieve client-specific variables in the client and session scope.

The hitCount value is an integer defining the number of times the client hasrequested a page within your application.The lastVisit value is a ColdFusionDateTime value equal to the date and time of the last page request within this applica-tion from this client.The timeCreated value is a ColdFusion DateTime value equalto the date and time the client store was created for this user in this application.

TipThe client scope should be used for values that you want to exist across user sessions. If you need to set a

variable whose lifetime should exist only for the extent of the current user session, use the session scope

instead.

One primary difference between the client scope and the session scope is that clientscope can only store simple values, whereas the session scope can include complex val-ues.A simple value is one that can be converted into string, which includes variables oftype string, boolean, datetime, and number.Variables such as structures and arrayscannot be stored in the client scope in their native form.You must store structures andarrays (or other complex data types) in the client scope, serialize the complex object to awddx string, and then store that value instead. For more on WDDX, see Chapter 21,“WDDX.”

7.5. Storing Client State Using the RegistryYou want to store client-state information in the application server registry.

TechniqueSet the <cfapplication> attribute clientStorage to registry to store clientstate data in the application server registry:

<cfapplication

name=”myApplication”

clientManagement=”yes”

clientStorage=”registry”>

10 0672324628 CH07 6/8/05 11:08 AM Page 97

Page 121: ColdFusion MX Developer's Cookbook (Developer's Library)

CommentsThis technique creates a ColdFusion application, initializes the client variable scope, andinstructs ColdFusion to use the application server system registry to store client scopeinformation.

ColdFusion installs with registry client storage as the default, so unless changes havebeen made in the ColdFusion administrator, you can omit the clientStorage attrib-ute and accept the registry as the default setting.

If your ColdFusion Application Server is on a UNIX machine, registry storage is notan option.Also note that you cannot use the registry storage option in a clustered appli-cation environment.

Although registry client storage is the default setting, there are many disadvantages.The primary disadvantage is that registry storage does not scale well for many clients.When using registry storage, each client is provided a singular registry entry. ColdFusionstores these entries in the registry locationHKEY_LOCAL_MACHINE\SOFTWARE\Macromedia\ColdFusion\CurrentVersion\Clients.You will have as manyentries in the registry as you have clients who have accessed applications on your application server.

7.6. Storing Client State Using CookiesYou want to store client state information in the application server registry.

TechniqueSet the <cfapplication> attribute clientStorage to cookie to store client statedata in client cookies.

<cfapplication

name=”myApplication”

clientManagement=”yes”

clientStorage=”cookie”>

CommentsThis technique creates a ColdFusion application, initializes the client variable scope, andinstructs ColdFusion to use cookies to store client scope information.

Cookies are encrypted text files sent to the client machine typically used to storesmall bits of information, such as client identifiers. Cookies are not human readable andare only accessible by the domain that created them.

Storing client scope data in cookies provides the attractive benefit of high scalability,as you aren’t using any application server resources to store client data. However, thereare also a number of disadvantages.

One disadvantage for storing state information in cookies is that some browsers limitcookie size—which prevents you from storing large amounts of data in the client scope,and ColdFusion throws an exception if you attempt to store too much data in a clientvariable.

98 Chapter 7 Application Flow

10 0672324628 CH07 6/8/05 11:08 AM Page 98

Page 122: ColdFusion MX Developer's Cookbook (Developer's Library)

The primary disadvantage related to using cookies to store client data is that users cansimply not accept cookies and can edit or delete cookies from their system. For thesetwo reasons, storing client data in cookies should be an option only if your users are in acontrolled environment and cannot edit cookie data, or if you are storing simple, non-essential data in the client scope.

7.7. Storing Client State Using a DatabaseYou want to store client state information in a database.

TechniqueSet the <cfapplication> attribute clientStorage to the name of a validColdFusion data source configured to store client scope data.

<cfapplication

name=”myApplication”

clientManagement=”yes”

clientStorage=”myDatasource”>

CommentsThis technique creates a ColdFusion application, initializes the client variable scope, andthen instructs ColdFusion to use the data source named myDatasource to store clientscope information.

To store client scope information in a database, you must first ensure the data sourceis configured to accept client state information. If the database type you are using sup-ports creating tables through SQL scripts, you simply need to create a blank database andpoint the client storage to that database. ColdFusion builds the table schema required tostore client scope data for you. If your database does not support SQL table creation, youneed to build the tables yourself. ColdFusion requires two tables to store client scopedata in a database: CDATA and CGLOBAL.These tables and their fields are described inTables 7.2 and 7.3, respectively.

Table 7.2 CDATA Table Columns, Data Types, and Descriptions

Column Name Data Type Description

cfid String of variable length at Stores the CFID and CFTOKEN for the least 64 characters appropriate user in the format CFID:CFTOKEN.

app String of variable length at Stores the name of the application used to least 64 characters create the client entry.

Data String of variable length with Stores pound-sign delimited client scope an indeterminate number of key/value combinations created by the total characters acceptable application.

997.7. Storing Client State Using a Database

10 0672324628 CH07 6/8/05 11:08 AM Page 99

Page 123: ColdFusion MX Developer's Cookbook (Developer's Library)

100 Chapter 7 Application Flow

Table 7.3 The CGLOBAL Table Column, Data Types, and Descriptions

Column Name Data Type Description

cfid String of variable length at least Stores the CFID and CFTOKEN for 64 characters the appropriate user in the format

CFID:CFTOKEN.

data String of variable length with an Stores pound-sign delimited client indeterminate number of total scope key/value combinations characters acceptable created by ColdFusion.

lvisit DateTime Stores the DateTime value represent-ing the last time this user visited theapplication.

NoteColdFusion does not create indexes on the tables it creates to store client scope information. If you want to

create indexes to improve performance, you should index the cfid columns of both tables.

Storing client scope information in databases is more often than not the ideal way tomanage client data.The disadvantage, obviously, is that you need access to a database system.

The advantages though are tremendous—you have complete control over the storageof the data, the system scales much better than when storing in the registry, the system ismuch more reliable than when storing in client cookies, and security responsibility isdelegated to the security options for your database system.

10 0672324628 CH07 6/8/05 11:08 AM Page 100

Page 124: ColdFusion MX Developer's Cookbook (Developer's Library)

8Exception Handling

8.0. IntroductionYou just learned about the various ways to control application flow in your ColdFusionapplication.The CFML programming language allows you to group statements into con-ditional blocks (<cfif> and <cfswitch>) and iterative blocks (<cfloop>).The use ofproper flow-control and code-formatting techniques can make your program easy tounderstand, even for someone unfamiliar with your code.

Traditional error handling in C and BASIC subroutines involved a demon that wouldobscure the logic of the most elegantly written program.Although essential, handlingerrors should never be the object of your program.After all, your error handling codewon’t even be executed if everything goes according to plan, right?

Error handling can also clutter an otherwise clean programming API.Traditionalfunctions not only had to return the expected result, they also had to return a myriad oferror codes and messages to report if anything went wrong.This often led to confusingsemantics, in which the result of the function was not the intended result but was,instead, an error code that your program had to check.The actual result was returned byreference through one of the function’s arguments. For example, the StructAppend()CFML function returns a true/false error code rather than a pointer to the changedstructure.The actual result is returned by reference via the struct1 argument.

Exception handling was invented to clean up and isolate error handling logic. C++was one of the first programming languages to support this new concept. ColdFusionhas long supported exception handling. ColdFusion MX has refined the exception-han-dling API a bit to provide additional error information to the programmer.This chapterexplores exception handling in ColdFusion MX.You will learn about the<cftry>/<cfcatch> tag syntax to trap and handle different types of errors.You willalso look at the <cfthrow>/<cfrethrow> tags for raising new exceptions in your pro-gram. Finally, you will build some actual examples that demonstrate proper ColdFusionerror handling.

11 0672324628 CH08 6/8/05 11:08 AM Page 101

Page 125: ColdFusion MX Developer's Cookbook (Developer's Library)

102 Chapter 8 Exception Handling

Before diving headlong into exceptions, pause for a moment to look at the way youwould handle errors without exception handling (and the way some programmers mightbe guilty of using).The following pseudocode illustrates cumbersome error handling.

// We will now attempt an operation, such as reading a file

<cfset errorcode = doSomething(arg1,arg2,arg3,result)>

<cfif errorcode eq error1>

// handle the first type of error

<cfelseif errorcode eq error2>

// handle the second type of error

<cfelseif errorcode == error3>

// handle the third error

...

<cfelseif errorcode == errorN>

// handle the nth error

</cfif>

// actual program logic goes here.

<cfoutput>#result#</cfoutput>

This pseudo-routine contains two lines of “getting-stuff-done” code and many, manymore lines of error handling.The error handling code is not the problem as much as itsplacement in the template. It breaks up the flow of the routine and confuses the algo-rithm. Notice, also, that the return value of the doSomething() function is an errorcode rather than something more useful.

ColdFusion provides a way to separate the error conditions from the main line algo-rithm through the use of the <cftry> and <cfcatch> tags. <cftry> creates a blockof potentially problematic code, whereas <cfcatch> isolates specific error-handlinglogic.You can use try and catch to simplify the pseudocode:

<cftry>

// Attempt an operation, returning a useful result

// rather than an error code.

<cfset result = doSomething(arg1,arg2,arg3)>

// actual program logic goes here>

<cfoutput>#result#</cfoutput>

<cfcatch type=”error1”>

// handle the first error type

</cfcatch>

<cfcatch type=”error2”>

// handle the second error type

</cfcatch>

...

<cfcatch type=”errorn”>

// handle the nth error type

</cfcatch>

</cftry>

11 0672324628 CH08 6/8/05 11:08 AM Page 102

Page 126: ColdFusion MX Developer's Cookbook (Developer's Library)

1038.1. Catching Exceptions

This incarnation of the program is much easier on the eyes.The code that you reallycare about (that is, the program’s primary logic) appears, uninterrupted, at the top of the<cftry> block.The error-handling logic takes a back seat to the main algorithm andappears at the end of the <cftry> block.This is as it should be.

Exception handling will enhance your program’s durability as well as its aesthetics. Byhandling ColdFusion errors in your code, you save your users from being exposed to theall-too-common “An error occurred while processing your request…”standard-issue error templates.

8.1. Catching ExceptionsYou want to anticipate and handle exceptions within your ColdFusion template.

TechniqueUse the <cftry> and <cfcatch> tags to anticipate and handle errors in yourColdFusion template.

<cftry>

<cffile action=”read” file=”this file doesn’t exist” variable=”thefile”>

<cfoutput>#thefile#</cfoutput>

<cfcatch>

The file you requested does not exist.

</cfcatch>

</cftry>

CommentsColdFusion exception handling is quite simple to understand and use.There are onlytwo little tags you need to worry about, so there is absolutely no excuse for not usingthem. Use <cftry> to isolate your mainline logic and <cfcatch> to respond to yourerrors. ColdFusion will abort processing the <cftry> block the moment an erroroccurs and will shift control to the appropriate <cfcatch> block.This exampleattempts to read a non-existent file.

Reading a file, like any I/O operation, is prone to failure. In this example, you antici-pate a possible error by isolating the logic in question with the <cftry> tag.You usethe <cfcatch> tag to handle the error within the application and display a friendlyerror message to the users.

11 0672324628 CH08 6/8/05 11:08 AM Page 103

Page 127: ColdFusion MX Developer's Cookbook (Developer's Library)

104 Chapter 8 Exception Handling

8.2. Catching Multiple ExceptionsYou want to catch multiple exceptions within your ColdFusion template.

TechniqueUse multiple instances of <cfcatch> within a single <cftry> block to handle differenttypes of errors.

<cftry>

<cfset thefilename = bad_variable_name&”.txt”>

<cffile action=”read” file=”#thefilename#” variable=”thefile”>

<cfoutput>#thefile#</cfoutput>

<cfcatch type=”expression”>

<!--- Catch errors in the filename expressions --->

The expression is not valid

</cfcatch>

<cfcatch type=”application”>

<!--- Catch errors in the <cffile> operation --->

The file you requested does not exist.

</cfcatch>

<cfcatch type=”any”>

<!--- Catch all other exceptions --->

Some other exception occurred

</cfcatch>

</cftry>

CommentsWhat happens if more than just one type of error can occur in the midst of a <cftry>block? ColdFusion allows you to specify multiple <cfcatch> blocks, one for each typeof error.The type attribute of the <cfcatch> tag specifies a specific exception type tobe caught.Table 8.1 lists the exception types supported by ColdFusion.

Table 8.1 ColdFusion Exception Types

Exception Type Description

Application Catches application exceptions.

Database Catches exceptions that occur during database operations.

Template Catches ColdFusion page exceptions.

Security Catches exceptions surrounding user security.

Object Catches exceptions thrown when working with objects.

MissingInclude Catches exceptions generated by a missing include template.

Expression Catches exceptions thrown by invalid CFML expressions.

Lock Catches exceptions thrown during synchronized code segments.

11 0672324628 CH08 6/8/05 11:08 AM Page 104

Page 128: ColdFusion MX Developer's Cookbook (Developer's Library)

Custom_Type Catches exceptions that are defined by you, the developer.

SearchEngine Catches exceptions thrown by the Verity search engine.Any The default. Catches any type of thrown exception.

This example catches, several types of exceptions. I modified the previous example touse a potentially erroneous expression to determine the filename.You must now catch atleast two types of exceptions:“expression” (to catch an exception in determining thefilename) and “application” (to catch an exception in the file I/O). It also catchesexpressions of type=”any” to be safe.

Astute readers may notice a potential ambiguity in the example’s exception handlingcode. Expression exceptions can be handled by <cfcatch> blocks with typeExpression or Any (likewise, I/O exceptions could be considered Application orAny). Both types of <cfcatch> blocks appear in the code, so where will expressionexceptions be handled? ColdFusion will always use the most precise <cfcatch> blockavailable for handling an exception. <cfcatch type=”any”> is used only as a lastresort, regardless of the order in which the different <cfcatch> blocks appear in thecode.

NoteIn addition to the primary 11 exception types, ColdFusion MX introduced over 50 new “advanced” exception

types for even more fine-grained control of your application. Consult the MX documentation for a full list-

ing of these new exception types.

8.3. Examining an ExceptionYou want to find out more information about an exception that you havecaught.

TechniqueUse the ColdFusion cfcatch structure to gather more detail about an exception.

<cftry>

<cfset thefilename = bad_variable_name&”.txt”>

<cffile action=”read” file=”#thefilename#” variable=”thefile”>

<cfcatch type=”any”>

<!--- Catch all other exceptions --->

<cfoutput>

A #cfcatch.type# exception occurred.

#cfcatch.message#: #cfcatch.detail#<br>

1058.3. Examining an Exception

Table 8.1 Continued

Exception Type Description

11 0672324628 CH08 6/8/05 11:08 AM Page 105

Page 129: ColdFusion MX Developer's Cookbook (Developer's Library)

106 Chapter 8 Exception Handling

<cfdump var=”#cfcatch.tagcontext#”>

</cfoutput>

</cfcatch>

</cftry>

CommentsJust knowing that an error occurred is often not enough. Usually you want to knowwhat error occurred and why it happened.You can access this information in a<cfcatch> block via the implicit cfcatch variable.This variable is populated withuseful information at the start of any <cfcatch> block.Table 8.2 lists the cfcatchstructure’s keys and values.

Table 8.2 The Contents of the cfcatch Variable

Key Value

cfcatch.detail A ColdFusion-supplied detailed message.This message con-tains HTML formatting and is intended to be displayed in aWeb page. Use this variable to help with debugging.

cfcatch.ErrorCode A string that represents a specific exception error code.Thisis used only with exceptions of type=”Custom”.

cfcatch.ErrNumber An internal expression error number that is specific toexceptions of type=”Expression”.

cfcatch.ExtendedInfo Custom error information that is not normally displayed.This is used with exceptions of type Custom andApplication.

cfcatch.LockName The name of the affected lock for exceptions oftype=”Lock”.This variable will contain the string“anonymous” if the lock’s name is unspecified.

cfcatch.LockOperation The lock operation that failed, causing a type=”Lock”exception to be thrown.Values may be Timeout, CreateMutex, or unknown.

cfcatch.Message A string representing the exception’s diagnostic message, ifavailable.

cfcatch.MissingFileName The name of the missing template in the case of an excep-tion of type=”MissingInclude”.

cfcatch.NativeErrorCode A database-specific error code that is native to the databasedriver.This variable is provided for exceptions oftype=”Database”.

cfcatch.SQLState SQL state information, if provided by the database driver,associated with exceptions of type=”database”.

cfcatch.TagContext An array of structures containing the stack trace of all tagsthat led to the exception, including the tag that threw theexception.

cfcatch.Type The exception type specified in the <cfcatch> block.

11 0672324628 CH08 6/8/05 11:08 AM Page 106

Page 130: ColdFusion MX Developer's Cookbook (Developer's Library)

1078.4. Throwing Exceptions

The example in the previous technique returns you to the familiar I/O example.Thecode is augmented to output some diagnostic information to help debug the problem.

The code includes a debug statement to the <cfcatch> block to output the expres-sion’s message, detail, and tagcontext variables. Note that you use the <cfdump>tag to automate the rendering of the contents of the cfcatch.tagcontent variable.This is a good way to become familiar with the values of the cfcatch structure.

8.4. Throwing ExceptionsYou want to throw custom exceptions in your application.

TechniqueUse the <cfthrow> tag to raise your own exceptions.

<cfthrow type=”MyException” message=”A custom exception occurred.”

detail=”This is an example of a custom ColdFusion exception.”>

CommentsColdFusion gives programmers the capability to create their own types of exceptionsthat can be thrown and caught just like standard exceptions. Custom exceptions enableyour CFML templates to communicate errors that are unique to your application.

You can (and should!) use custom exceptions in your application to propagate errorconditions.This technique is invaluable when you are writing custom tags or functions.Custom exceptions are the preferred way to notify the calling CFML template thatsomething went horribly wrong.

You can roll your own exceptions with the <cfthrow> tag.The tag uses the follow-ing syntax:<cfthrow

type=”exception_type”

message=”message”

detail=”detailed_description”

errorCode=”error_code”

extendedInfo=”extra_useful_information”

object=”java_exception_object”>

The type attribute can be any of the following: Application, Any, or a customexception string of your choosing.The message attribute should describe the excep-tion.The detail attribute should provide useful documentation to aid in debugging.ColdFusion will display the value of this attribute if the exception is not caught.TheerrorCode and extendedInfo attributes are left for you to fill out or leave blank.These optional attributes can be used to provide extra information about a user-definedexception.The object attribute allows you to pass in a subclass of the Java Exceptionobject.You must first define this exception by using the <cfobject> tag.

11 0672324628 CH08 6/8/05 11:08 AM Page 107

Page 131: ColdFusion MX Developer's Cookbook (Developer's Library)

108 Chapter 8 Exception Handling

The previous technique shows an example of throwing a custom exception.Theexception is of type MyException and includes a brief message and a more detailedexplanation of the error.

NoteSome compilers, such as the Java compiler, will not compile a source file until all possible exceptions are

caught or re-thrown in some fashion. Compile-time error checking like this can help strengthen the quality

of your code. The ColdFusion compiler does not warn you about the potential for uncaught exceptions. So

be vigilant, ColdFusion developers.

Custom exceptions are handled exactly like their standard counterparts. Custom excep-tions are an elegant means for your ColdFusion templates to report errors.You should beliberal with your exception types. Many programmers fall into the trap of throwing andcatching exceptions at the broadest level.Try to avoid throwing and catching too manyexceptions with type=”Any”.Although doing so may seem expedient at first, you willbe robbing your application of some flexibility.An application with many small andfocused <cfcatch> blocks is more extensible than an application with fewer, but muchlarger, <cfcatch type=”any”> blocks.

8.5. Re-Throwing ExceptionsYou want to propagate an exception up to the calling page.

TechniqueUse the <cfrethrow> tag to defer the handling of an exception to a template higherup on the call stack.

<cftry>

<cfquery...>

<cfcatch type=”database”>

<cfif cfcatch.NativeErrorCode eq “100012”>

<!--- ignore this benign error --->

<cfelse>

<!--- uh oh. Better let everyone know --->

<cfrethrow>

</cfif>

</cfcatch>

</cftry>

CommentsWhat happens if you catch something that you did not mean to catch? Ask any old fish-erman this question—just throw the darned thing back. ColdFusion provides the<cfrethrow> tag to do just that.

11 0672324628 CH08 6/8/05 11:08 AM Page 108

Page 132: ColdFusion MX Developer's Cookbook (Developer's Library)

1098.5. Re-Throwing Exceptions

Sometimes re-throwing an exception is the most appropriate course of action to take.This is usually the case if the template that caught the exception is not completely surewhat to do with it. In this circumstance, it is generally preferable to re-throw the excep-tion rather than to make a bad guess.

For example, a database query can throw many types of exceptions (distinguished bythe SQLState or NativeErrorCode cfcatch variables).All of these exceptions willfall under the broad type, database.Your template is left to decide which types of databaseexceptions it can handle safely and which are important enough to report to the callingtemplate.The pseudocode fragment shown in the previous technique demonstrates thisidea.

Note that the <cfrethrow> tag does not require any attributes.This is because thetag operates in the scope of the <cfcatch> block in which it is placed. It merely prop-agates the current exception, as-is, up the call stack in order for a higher-level templateto handle the error.

11 0672324628 CH08 6/8/05 11:08 AM Page 109

Page 133: ColdFusion MX Developer's Cookbook (Developer's Library)

11 0672324628 CH08 6/8/05 11:08 AM Page 110

Page 134: ColdFusion MX Developer's Cookbook (Developer's Library)

IIIUsing Utility Tags

9 Charting Data

10 Files and Directories

11 Using Internet Protocols

12 Using Verity

13 User Authentication and Authorization

12 0672324628 Part 03 6/8/05 11:08 AM Page 111

Page 135: ColdFusion MX Developer's Cookbook (Developer's Library)

12 0672324628 Part 03 6/8/05 11:08 AM Page 112

Page 136: ColdFusion MX Developer's Cookbook (Developer's Library)

9Charting Data

9.0. IntroductionData can be boring.Although spreadsheets and list views may technically provide all theinformation necessary to make business decisions, they don’t necessarily make for themost visually appealing applications. Determining the best way to visually display infor-mation is one of the primary roles of a ColdFusion developer, and ColdFusion providesthe creatively inclined many tools to assist in this ever evolving technical art.The<cfchart> tag is one of these tools.

There are numerous reasons to include charts in Web applications. Charts are visuallyappealing; they add color and spice to your data, and quite simply, they add to the userexperience.This chapter discusses the charting capabilities provided by ColdFusion MXand how to best use that functionality to obtain your desired results.

9.1. Creating a Simple ChartYou want to create a simple chart.

TechniqueUse cfchart, cfchartseries, and cfchartdata to create a simple chart.

<cfchart>

<cfchartseries type=”scatter”>

<cfchartdata value=”5”>

<cfchartdata value=”8”>

<cfchartdata value=”6”>

</cfchartseries>

</cfchart>

13 0672324628 CH09 6/8/05 11:08 AM Page 113

Page 137: ColdFusion MX Developer's Cookbook (Developer's Library)

114 Chapter 9 Charting Data

CommentsTo create the most basic chart in ColdFusion, you must create a chart object using the<cfchart> tag, you must create a chart series object inside of the chart object using the<cfchartseries> tag, and then you must define the value points for the series.

The code in the previous technique provides values only for the required items need-ed to create a chart.As you can probably imagine, there are numerous optional attributesyou can use to further manipulate the display and behavior of a chart. Execute the codein the previous technique and take a look at the generated chart.The next few sectionscover how to manage the appearance and behavior of the chart container, the series inthe chart, as well as the individual data points.

9.2. Managing the Chart ContainerYou want to manage the chart container portion of a chart object.

TechniqueProvide values for the optional <cfchart> attributes to manage the chart containerportion of a chart object.

<cfchart

chartHeight = “500”

chartWidth = “500”

gridlines = “11”

scaleTo = “10”

tipStyle=”mouseDown”>

<cfchartseries type=”scatter”>

<cfchartdata value=”5”>

<cfchartdata value=”8”>

<cfchartdata value=”6”>

</cfchartseries>

</cfchart>

CommentsRarely will you create a chart in ColdFusion and accept the default values for all theoptional attributes in the <cfchart> tag as you did in section 9.1.You will most likelycontrol the display of the chart to complement the design of your specific application.There are numerous optional attributes you can supply to the cfchart tag to controlthe chart container. Basically, the chart container is responsible for everything in thechart except for the actual series and data points.That means you can provide attributes

13 0672324628 CH09 6/8/05 11:08 AM Page 114

Page 138: ColdFusion MX Developer's Cookbook (Developer's Library)

1159.2. Managing the Chart Container

defining the width and height of the chart container, manage the format and display ofthe axis values, control display of the legend, and define colors for different sections ofthe container, among other things. In the previous technique, you defined the height andwidth of the chart container, defined how many gridlines should appear on the y-axis ofthe chart, scaled the chart to a specific value on the y-axis, and adjusted the tooltipbehavior to appear on mouseDown.

These are just a few of the many attributes available for the <cfchart> tag.Table 9.1lists all available attributes and values and describes their respective behaviors.

Table 9.1 Optional <cfchart> Attributes and Behaviors

Attribute Optional Values and Behaviors

backgroundColor Hexadecimal value or named Web color. Controls the colorbetween the border and the chart data area. Default is white.

chartHeight Desired chart height in pixels. Default is 240.

chartWidth Desired chart width in pixels. Default is 320.

dataBackgroundColor Hexadecimal value or named Web color. Controls the colorbetween the border and the chart data area. Default is white.

font One of four font names: arial, arialUnicodeMS, times, orcourier. Default is arial.

fontBold Defines font bold style. Yes or No. Default is No.

fontItalic Defines font italic style. Yes or No. Default is No.

fontSize Defines font size as an integer value. Default is 11.

foregroundColor Hexadecimal value or named Web color. Controls the color ofobjects on the foreground such as the gridlines, the axis lines,the axis value markers, and the border. Default is black.

format Defines the format of the chart output.Accepted values areflash, jpg, and png. Default is flash.

gridlines Integer number of gridlines to display on the chart value axis.Default is 3.

labelFormat Format to display values on y-axis.Accepted values are currency, date, number, and percent. Default is number.

markerSize Desired marker size in pixels. Default is determined at runtime.

name String value for creating a ColdFusion variable from the outputof the chart. Primarily used for creating a chart and then writingthe chart to a file. Note also providing a value for this attributecauses the chart to not display on the resulting page.

pieSliceStyle For a pie chart, defines whether the pie is sliced or not.Accepted values are sliced and solid. Default is sliced.

rotated Creates a horizontal bar chart by rotating the graph axis. Yes orNo. Default is No.

13 0672324628 CH09 6/8/05 11:08 AM Page 115

Page 139: ColdFusion MX Developer's Cookbook (Developer's Library)

116 Chapter 9 Charting Data

scaleFrom Integer value for minimum y-axis point. Default is determinedat runtime.

scaleTo Integer value for maximum y-axis point. Default is determinedat runtime.

seriesPlacement For charts with more than one series, defines the position of theseries combinations.Accepted values are cluster, default,percent, and stacked. Default is default.

show3d Determines whether the chart will display as three-dimensional.Yes or No. Default is No.

showBorder Determines whether a border will be placed around the entirechart container. Yes or No. Default is No.

showLegend For a chart with more than one series, determines whether alegend is displayed. Yes or No. Default is Yes if there is morethan one series.

showMarkers For series with type of curve, line, and scatter, determineswhether markers are shown at value points. Yes or No. Defaultis Yes.

showXGridlines Determines whether grid is shown for x-axis. Yes or No.Default is No.

showYGridlines Determines whether grid is shown for y-axis. Yes or No.Default is Yes.

sortXAxis Alphabetizes values along the x-axis. Yes or No. Default is No.

tipBGColor Hexadecimal value or named Web color. Controls the back-ground color of the value points in the chart. Note this appliesonly to flash format charts. Default is white.

tipStyle Defines which action causes the tip to show for a value point.Accepted values are mouseDown, mouseOver, and Off. If chartformat is flash, mouseDown requires a mouse left-click to showthe tip. If not flash, the mouseDown behavior is the same asmouseOver. mouseOver shows the tip on a mouse fly-over. Offturns off the tip functionality. Default is mouseOver.

url Defines the URL to jump to when a value point is clicked. Nodefault.

xAxisTitle String value to display as a title for the x-axis. No default.

xOffset For 3D charts, any number between –1 and 1. Defines the angleto use in the third dimension for the x-axis. Default is .1.

yAxisTitle String value to display as a title for the y-axis. No default.yOffset For 3D charts, any number between –1 and 1. Defines the angle

to use in the third dimension for the y-axis. Default is .1.

Table 9.1 Continued

Attribute Optional Values and Behaviors

13 0672324628 CH09 6/8/05 11:08 AM Page 116

Page 140: ColdFusion MX Developer's Cookbook (Developer's Library)

1179.3. Managing Chart Series

9.3. Managing Chart SeriesYou want to manage the series objects inside a chart object.

TechniqueProvide values for <cfchartseries> attributes to manage the series inside a chartobject.

<cfchart>

<cfchartseries

type = “area”

paintStyle = “shade”>

<cfchartdata value = “5”>

<cfchartdata value = “8”>

<cfchartdata value = “6”>

<cfchartdata value = “6”>

<cfchartdata value = “5”>

</cfchartseries>

<cfchartseries

type = “line”

markerstyle = “diamond”>

<cfchartdata value = “12”>

<cfchartdata value = “10”>

<cfchartdata value = “8”>

<cfchartdata value = “10”>

<cfchartdata value = “9”>

</cfchartseries>

</cfchart>

CommentsSection 9.2 defined how to control the display and behavior of a chart container.A chartcontainer is useless without a series of data to actually populate the chart.You managethe display of the series object using the <cfchartseries> tag.You use this tag todefine the type of series to display the style and color of the markers among otherattributes.

Table 9.2 lists all available <cfchartseries> attributes and values and describestheir respective behaviors.A number of these optional attributes involve using a queryobject as data for populating the chart. Using queries to create graphs is discussed furtherin the next section.

13 0672324628 CH09 6/8/05 11:08 AM Page 117

Page 141: ColdFusion MX Developer's Cookbook (Developer's Library)

118 Chapter 9 Charting Data

Table 9.2 Optional <cfchartseries> Attributes and Behaviors

Attribute Optional Values and Behaviors

colorList Hexadecimal value or named Web color. Used only for chart series withtype of Pie. Controls the colors displayed for each value in the chart.Default is determined at runtime.

itemColumn Defines which column of a query object represents the item along the x-axis.

markerStyle Determines the display style of value points when chart is of type curve,line, and scatter.Accepted values are circle, diamond, letter, mcross,rectangle, rcross, snow, and triangle. Default is rectangle.

paintStyle Determines the display style of a filled data series.Accepted values arelight, plain, raise, and shade.

query The name of the ColdFusion query object containing the itemColumnand valueColumn to populate the data series.

seriesColor Hexadecimal value or named Web color. Controls the color of the seriesobject.

seriesLabel String name of the series; appears in the tip displayed for each value pointand in the legend if more than one series is defined.

type One of the 10 supported ColdFusion chart types: area, bar, cone, curve,cylinder, line, pie, pyramid, scatter, or step.

valueColumn Defines which column of a query object represents the item along the y-axis.

Charts with multiple series are also useful tools.You can create multiple series of datawithin a chart by using more than one <cfchartseries> tag. It is up to the chartdesigner, of course, to determine the best way to present the data within the chart—witha number of tools at your fingertips, the <cfchartseries> helps you create the mostappealing, useful chart for your application.

The previous technique created a chart with two series.The first series is an area typeseries with shaded fill color.The second series is a line series with diamond value points.You can add as many series to your chart as you see fit but be careful not to clutter theinformation so much that it becomes difficult to understand.

The only required attribute for <cfchartseries> is the type attribute.You candefine the type of series as one of the following: area, bar, cone, curve, cylinder, line, pie,pyramid, step, and scatter.

Figures 9.1 through 9.3 display the many different types of charts, using the code inListing 9.1. Note that if the cfchart attribute show3d was not set to “yes” that thebar and cylinder chart types would look identical, as would the cone and pyramidtypes.

13 0672324628 CH09 6/8/05 11:08 AM Page 118

Page 142: ColdFusion MX Developer's Cookbook (Developer's Library)

1199.3. Managing Chart Series

Listing 9.1 The 10 Supported CFMX Chart Types

<cfset chartList = “area,bar,cone,curve,cylinder,line,pie,pyramid,step,scatter”>

<cfloop list=”#chartList#” index=”i”>

<cfchart show3d = “yes”>

<cfchartseries type = “#i#”>

<cfchartdata value = “5”>

<cfchartdata value = “8”>

<cfchartdata value = “6”>

</cfchartseries>

</cfchart>

&nbsp;&nbsp;

</cfloop>

0 1 2 0 1 2

8

7.111

6.222

5.333

4.444

3.556

2.667

1.778

0.889

0

8

7.111

6.222

5.333

4.444

3.556

2.667

1.778

0.889

0

0 1 2

8

7.111

6.222

5.333

4.444

3.556

2.667

1.778

0.889

0

0 1 2

8

7.111

6.222

5.333

4.444

3.556

2.667

1.778

0.889

0

Figure 9.1 Chart types: area, bar, cone, and curve.

13 0672324628 CH09 6/8/05 11:08 AM Page 119

Page 143: ColdFusion MX Developer's Cookbook (Developer's Library)

120 Chapter 9 Charting Data

Figure 9.2 Chart types: cylinder, line, pie, and pyramid.

0 1 2 0 1 2

8

7.111

6.222

5.333

4.444

3.556

2.667

1.778

0.889

0

8

7.111

6.222

5.333

4.444

3.556

2.667

1.778

0.889

0

0 1 2

8

7.111

6.222

5.333

4.444

3.556

2.667

1.778

0.889

0

0

1

2

5(26%)

8(42%)

6(32%)

0 1 2 0 1 2

8

7.111

6.222

5.333

4.444

3.556

2.667

1.778

0.889

0

8

7.111

6.222

5.333

4.444

3.556

2.667

1.778

0.889

0

Figure 9.3 Chart types: step and scatter.

13 0672324628 CH09 6/8/05 11:08 AM Page 120

Page 144: ColdFusion MX Developer's Cookbook (Developer's Library)

9.4. Populating a Chart Series with ExplicitValues

You want to define data points inside a chart.

TechniqueUse the <cfchartdata> tag to explicitly define data points within a chart series.

<cfchart>

<cfchartseries type = “bar”>

<cfchartdata item = “January” value = “6”>

<cfchartdata item = “February” value = “8”>

<cfchartdata item = “March” value = “5”>

</cfchartseries>

</cfchart>

CommentsThe <cfchartdata> tag is used to explicitly define data points to populate a chartseries. <cfchartdata> accepts one required and one optional attribute.The requiredattribute is value and it must be a simple value.The value represents the y-axis.Theoptional attribute is item. Item represents the label for the x-axis.

NoteThe item attribute of the <cfchartdata> tag must contain a simple value, because ColdFusion must

be able to convert the value to a numeric. Simple values include variables of the following types:

boolean, date/time, string, and numbers.

9.5. Populating Charts with Query ValuesYou want to use a query object to define the data points inside a chart.

TechniqueTo populate a chart with query data, use the appropriate cfchartseries optionalattributes to define the name of the query used, the column representing the x-axis, andthe column representing the y-axis.

<cfchart>

<cfchartseries

type = “bar”

query = “myQuery“

itemColumn = “itemColumn”

valuecolumn = “valueColumn”

1219.5. Populating Charts with Query Values

13 0672324628 CH09 6/8/05 11:08 AM Page 121

Page 145: ColdFusion MX Developer's Cookbook (Developer's Library)

/>

</cfchart>

CommentsCreating graphs from ColdFusion query objects is a powerful feature of cfchart.(Formore information on ColdFusion query objects, see Chapter 5,“Queries.”) To takeadvantage of this feature, you need to provide a valid query object name as the value forthe query attribute of the <cfchartseries> tag.You also need to define which col-umn of the query contains data for the x-axis (or valueColumn) and which columncontains data for the y-axis (or itemColumn).

9.6 Implementing Click-Through Behaviors inCharts

Youc want to allow the users to click a specific value in the chart and execute a URL.

TechniqueUse the url attribute of the <cfchart> tag to define the target URL on a click event.

<cfchart url=”chart.cfm”>

<cfchartseries type = “bar”>

<cfchartdata item = “January” value = “6”>

<cfchartdata item = “February” value = “8”>

<cfchartdata item = “March” value = “5”>

</cfchartseries>

</cfchart>

CommentsThe url attribute of the <cfchart> tag enables you to click through charts and drilldown into more specific data or jump to another URL altogether. Note however thatthe same URL is used for the entire chart. ColdFusion does provide a variable scope forthe developer to capture which series, value, and label the user clicked.These variablesappear syntactically slightly different than other ColdFusion variable scopes.They arenamed SeriesLabel, ItemLabel, and Value for the clicked series, item, and value,respectively. Listing 9.2 adds to the technique code to pass through these values. Noticethe dollar signs ($) encasing the variable names in the url attribute.

Listing 9.2 Chart Drill Down with the url Attribute

<cfchart url=”chart.cfm?item=$itemLabel$&value=$value$&series=$seriesLabel$”>

<cfchartseries type = “bar” seriesLabel = “Items by Month”>

<cfchartdata item = “January” value = “6”>

<cfchartdata item = “February” value = “8”>

122 Chapter 9 Charting Data

13 0672324628 CH09 6/8/05 11:08 AM Page 122

Page 146: ColdFusion MX Developer's Cookbook (Developer's Library)

1239.7 Administering Charts Through the ColdFusion Administrator

<cfchartdata item = “March” value = “5”>

</cfchartseries>

</cfchart>

9.7 Administering Charts Through theColdFusion Administrator

You want to manage chart behavior through the ColdFusion Administrator.

TechniqueOpen ColdFusion Administrator (/cfide/Administrator.index.cfm), log in, andclick Charting from the left navigation bar to administer chart behavior.

CommentsThe ColdFusion MX administrator panel provides a management area for chart-specificsettings.Through the administrator you can manage where charts are stored, how manycharts to cache, the maximum number of charting threads to run at a given time, andthe location to store cached charts.

You can choose to have charts cached in memory or on disk, the default being ondisk.To serve cached charts faster you can choose to have them stored in memory. If youstore them in memory they will serve up faster, although you are reserving a block ofmemory in which to store them. If you manage a memory-intensive Cold Fusion appli-cation, it is better to store the charts on disk.

You can also define how many charts to store in the cache.The default is 50.Thismeans that once the 51st chart is requested, the oldest is removed from the cache andthe new request takes its place.

By default, ColdFusion will allow four charting threads to run at a given time.Youcan set this number anywhere between 1 and 5.The higher this number, the more stressplaced on your application (although only at times when multiple charts are requestedsimultaneously).

If you choose to store the chart cache on disk, which is the default setting,ColdFusion needs a block of space to store the images or Flash files. By default, thecache directory is [install drive letter]:\CFusionMX\charting\cache. Ifnecessary, you can change this directory to any location.

As every application is different, there is no global optimal setting for administeringcharts. However, if you begin to experience slow response in your charting applications,discuss these issues with your ColdFusion MX System Administrator to determine thebest charting settings for your application.

Listing 9.2 Continued

13 0672324628 CH09 6/8/05 11:08 AM Page 123

Page 147: ColdFusion MX Developer's Cookbook (Developer's Library)

13 0672324628 CH09 6/8/05 11:08 AM Page 124

Page 148: ColdFusion MX Developer's Cookbook (Developer's Library)

10Files and Directories

10.0. IntroductionWorking with files and directories is a powerful function of ColdFusion MX. Using file-and directory-management tags, you can upload files from a client machine, traverse thefile system on the application server, and manipulate files and directories on the applica-tion server. In this chapter, you learn how to use the <cffile> and <cfdirectory>tags to manipulate your file system.

10.1. Reading FilesYou want to read a file from the application server’s file system.

TechniqueUse the <cffile> tag to read the contents of a text file on the application server’s filesystem.

<cffile

action=”read”

variable=”filecontents”

file=”c:\documents\myFile.txt”>

CommentsColdFusion provides you the capability to read files from the application server file sys-tem through the action=”read” setting on a <cffile> tag.There are three requiredattributes and one optional attribute for the read action of a cffile.These attributesare explained in detail in Table 10.1.

14 0672324628 CH10 6/8/05 11:08 AM Page 125

Page 149: ColdFusion MX Developer's Cookbook (Developer's Library)

126 Chapter 10 Files and Directories

Table 10.1 Read Action cffile Attributes

Attribute Description

action Required. Must be set to “read” for a read action.

variable Required. Defines the name of a variable to contain the contents of the file.

file Required. Defines the path to the file on the application server file system.charset Optional. Defines the character set of the file contents. Default is UTF-8.

Once you execute the cffile call, the contents of the file are available by referencingthe variable name specified by the variable attribute.To display the contents of the file,simply wrap <cfoutput> tags and pound signs around the variable name in your tem-plate, like so:

<cfoutput>#filecontents#</cfoutput>

ColdFusion also provides the capability to read binary files through the readBinaryvalue of the action attribute.This populates the variable name defined in the variableattribute with the actual binary data stored in the requested file. If you need to read abinary file from the file system and then transfer that data through a form or need towrite the contents to another file, you must use the ToBase64() function to convertthe returned binary data into its Base64 equivalent.

10.2. Writing FilesYou want to create a file on the application server’s file system.

TechniqueUse the <cffile> tag to write a file to the application server’s file system.<cfset theContent = “Content to place in a new file”>

<cffile

action = “write”

file = “c:\documents\testfile.txt”

output = “#theContent#”

attributes = “readOnly”

addNewLine = “No”>

CommentsColdFusion provides you the capability to write files to the application server file system through the action=”write” setting on the <cffile> tag.

When using <cffile> with the action attribute set to “write”, there are threerequired and four optional parameters.These parameters are described in detail in Table 10.2.

14 0672324628 CH10 6/8/05 11:08 AM Page 126

Page 150: ColdFusion MX Developer's Cookbook (Developer's Library)

12710.3. Appending to Files

Table 10.2 Write Action cffile Attributes

Attribute Description

action Required. Must be set to “write” for a write action.

file Required. Defines the absolute path for the new file, including the new file-name.Windows uses backslashes in the absolute path; UNIX systems use for-ward slashes.r a write action.

output Required. Contains the content to place inside the new file.

addNewLine Optional.Accepted values are Yes and No. If Yes, a new line is appended tothe end of the content contained in the output attribute. If No, no new lineis appended. Default is Yes.

attributes Optional list of attributes to set on the new file.

charset Optional. Defines the character set used to create the new file. Default isUTF-8.

mode Optional. Defines the permission set to UNIX files.

Note that if the file defined in the file attribute of a write action <cffile> callalready exists (and if the permissions are set to allow an overwrite on the file system), thecontent provided in the output attribute will overwrite the content in the existing file.If you want to append to a file instead of overwriting it, see the technique provided inthe following section.

10.3. Appending to FilesYou want to append content to an existing file on the application server’s filesystem.

TechniqueUse the <cffile> tag to append content to an existing file on the application server’sfile system.

<cfset theContent = “New content to place in a new file”>

<cffile

action = “append”

file = “c:\documents\testfile.txt”

output = “#theContent#”

addNewLine = “No”>

CommentsColdFusion provides you the capability to append to existing files on the applicationserver file system through the action=”append” setting on the <cffile> tag.

14 0672324628 CH10 6/8/05 11:08 AM Page 127

Page 151: ColdFusion MX Developer's Cookbook (Developer's Library)

128 Chapter 10 Files and Directories

When using <cffile> with the action attribute set to “append”, there are threerequired and four optional parameters.These parameters are described in detail in Table 10.3.

Table 10.3 Append Action cffile Attributes

Attribute Description

action Required. Must be set to “append” for an append action.

file Required. Defines the absolute path for the existing file including the newfilename.Windows uses backslashes in the absolute path; UNIX systems useforward slashes.

output Required. Contains the content to append to the existing file.

addNewLine Optional.Accepted values are Yes and No. If Yes, a new line is appended tothe end of the content contained in the output attribute. If No, no new lineis appended. Default is Yes.

attributes Optional list of attributes to set on the new file.

charset Optional. Defines the character set used to create the new file. Default isUTF-8.

mode Optional. Defines the permission set to UNIX files.

Note that if the file defined in the file attribute does not already exist, the appendaction will behave exactly like a write action. It will write a new file to the file systemwithout throwing an exception. If you only want to append content to an existing file,you first need to use the FileExists() function to determine whether the file doesindeed exist.The following code provides an example of using FileExists() in con-junction with an append action <cffile> call:

<cfset myPath = “c:\documents\myfile.txt”>

<cfif FileExists(myPath)>

<cfset theContent = “New content to place in a new file”>

<cffile

action = “append”

file = “#myPath#”

output = “#theContent#”

addNewLine = “No”>

<cfoutput>New content added to file #myPath#</cfoutput>

<cfelse>

<cfoutput>File #myPath# doesn’t exist!</cfoutput>

</cfif>

In the previous code, the FileExists() function determines whether the file definedby the myPath variable already exists. If it does exist, content is appended to the file anda message is displayed confirming the action. If the file doesn’t exist, a message is dis-played stating that the file doesn’t yet exist.

14 0672324628 CH10 6/8/05 11:08 AM Page 128

Page 152: ColdFusion MX Developer's Cookbook (Developer's Library)

12910.4. Uploading Files

10.4. Uploading FilesYou want to upload files from a client machine to the application server’s filesystem.

TechniqueUse the <cffile> tag to upload files from a client machine to the application server’sfile system.

<cfif isDefined(“submitted”)>

<cffile

action=”upload”

filefield=”myFile”

destination=”c:\documents\”

nameConflict=”makeUnique”>

<cfset success = true>

</cfif>

<html>

<body>

<form

name=”myForm”

action=”./fileUpload.cfm”

method=”POST”

enctype=”multipart/form-data”>

<cfif isDefined(“success”)>

File Uploaded!<br>

</cfif>

Please browse for the file to upload and click submit<br>

<input type=”file” name=”myFile”><br>

<input type=”hidden” name=”submitted”>

<input type=”submit”>

</form>

</body>

</html>

CommentsColdFusion provides you the capability to upload files to the application server file system through the action=”upload” setting on the <cffile> tag.

When using <cffile> with the action attribute set to “upload”, there are threerequired and four optional parameters.These parameters are described in detail in Table 10.4.

14 0672324628 CH10 6/8/05 11:08 AM Page 129

Page 153: ColdFusion MX Developer's Cookbook (Developer's Library)

130 Chapter 10 Files and Directories

Table 10.4 Upload Action cffile Attributes

Attribute Description

action Required. Must be set to upload for an upload action.

destination Required. Defines the absolute path destination for the uploaded file,excluding the filename.Windows uses backslashes in the absolute path;UNIX systems use forward slashes.

filefield Required. Defines the name of the form input that contains the file to beuploaded.

accept Optional. Defines a comma-delimited list of accepted MIME types forupload.

attributes Optional list of attributes to set on the new file.

mode Optional. Defines the permission set to UNIX files.nameConflict Optional. Instructs ColdFusion what to do in case of a naming conflict.

Accepted values are Error, MakeUnique, Skip, and Overwrite.

NoteThe value of the filefield attribute is simply the name of the field containing the path of the file to be

uploaded. Do not wrap the name of this field in pound signs as doing so will dereference the variable. This is

a common mistake when uploading files with <cffile>.

The upload action of <cffile> can only be used in conjunction with a form con-taining a file to be uploaded. In the previous technique, the user is first presented with aform prompting for a file to upload.After the user clicks submit, ColdFusion uploads thefile using the <cffile> tag and presents the user with a message stating that the filewas uploaded.

There are two requirements of the form tag necessary to create a form capable ofuploading a file to the server. First, the method argument of the form tag must be set toPOST.A form without the method argument defaults to a method of GET—which doesnot permit sending multipart data as a GET means that form data is posted through theURL. Secondly, the form must have an enctype argument set to “multipart/form-data”.Without these two arguments set correctly, your form will simply post theclient path of the file attempting upload, not the file itself. Note that if you useColdFusion <cfform> tags instead of HTML <form> tags, the method defaults toPOST instead of GET, although the enctype does not default to multipart/form-data.

It is always a good idea to use the <cffile> “accept” parameter when uploadingfiles. Using this parameter specifies which file types your form will accept. If the userattempts to upload a file which has a MIME type not found in the accept parameter,ColdFusion will throw an InvalidUploadTypeException exception.Without thepresence of the accept parameter, malicious users are permitted to upload whateverthey choose.

14 0672324628 CH10 6/8/05 11:08 AM Page 130

Page 154: ColdFusion MX Developer's Cookbook (Developer's Library)

13110.4. Uploading Files

The nameConflict attribute is also useful, especially in high traffic situations. If twousers attempt to upload a file with the same name, you can control the behavior of thefiles with the nameConflict attribute.Accepted values for the nameConflict attrib-ute are Error, MakeUnique, Skip, and Overwrite. Specifying Error instructsColdFusion not to save the file and to throw a FileOverwriteException exception.Specifying MakeUnique instructs ColdFusion to save the file but to provide it a newname (the new name of the file is stored in the cffile.serverFile variable, dis-cussed later in this section). Specifying Skip instructs ColdFusion not to save the file butto continue processing the rest of the page. Specifying Overwrite instructs ColdFusionto overwrite the existing file with the new one.

When you execute the upload action on cffile, ColdFusion creates a special read-only structure named cffile which provides the developer detailed information aboutthe upload attempt.The complete contents of the cffile structure are detailed in Table 10.5.

Table 10.5 cffile Keys and Descriptions

Key Name Description

attemptedServerFile The name of the file ColdFusion attempted to save.

clientDirectory The absolute path on the client machine of the file ColdFusionattempted to upload.

clientFile The name of the file ColdFusion uploaded from the clientmachine, including the extension.

clientFileExt The extension (without the .) of the file ColdFusion attempted toupload.

clientFileName The name of the file ColdFusion uploaded from the clientmachine, excluding the extension.

contentSubType The MIME subtype of the file ColdFusion saved.

contentType The MIME content type of the file ColdFusion saved.

fileExisted Boolean value defining whether a file with the same path andname already exists on the application server file system.

fileSize The size of the file ColdFusion saved in kilobytes.

fileWasAppended Boolean defining whether ColdFusion appended the uploaded fileto another file on the application server file system.

fileWasOverwritten Boolean defining whether ColdFusion overwrote an existing filewith the new file.

fileWasRenamed Boolean defining whether ColdFusion renamed the file beforesaving it on the application server file system.

fileWasSaved Boolean defining whether ColdFusion saved the file on the appli-cation server file system.

oldFileSize The size of the file ColdFusion overwrote to save the new file ifan overwrite was necessary.

14 0672324628 CH10 6/8/05 11:08 AM Page 131

Page 155: ColdFusion MX Developer's Cookbook (Developer's Library)

132 Chapter 10 Files and Directories

serverDirectory The absolute path of the directory used to save the file on theapplication server file system.

serverFile The name of the file ColdFusion saved on the application serverfile system, including the extension.

clientFileExt The extension (without the .) of the file ColdFusion saved on theapplication server file system including the extension.

clientFileName The name of the file ColdFusion saved on the application serverfile system, including the extension.

timeCreated Date stamp defining the time the file was saved on the applicationserver file system.

timeLastModified Date stamp defining the time the file was last modified on theapplication server file system.

As with all structures, a useful way to display the keys and values returned with thecffile collection is with the <cfdump> tag. For more information on how to use<cfdump> with structures, and more on structures in general, see Chapter 4,“Structures.”

The structure returned from the upload action on a cffile execution has the basename cffile. So to reference the directory path ColdFusion used to save an uploadedfile, you simply use the following code after the cffile execution:

<cfoutput>

The file was saved to: #cffile.serverDirectory#

</cfoutput>

10.5. Manipulating FilesYou want to move, rename, copy, or delete a file on the application server’s filesystem.

TechniqueUse the <cffile> tag to move, rename, copy, or delete an existing file on the applica-tion server file system.

<cfset myPath = “c:\documents\myfile.txt”>

<cfset myNewPath = “c:\documents\new\”>

<cfif FileExists(myPath)>

<cffile

action = “move”

source = “#myPath#”

destination = “#myNewPath#”>

Table 10.5 Continued

14 0672324628 CH10 6/8/05 11:08 AM Page 132

Page 156: ColdFusion MX Developer's Cookbook (Developer's Library)

13310.5. Manipulating Files

<cfoutput>File #myPath# moved to #myNewPath#</cfoutput>

<cfelse>

<cfoutput>File #myPath# doesn’t exist!</cfoutput>

</cfif>

CommentsColdFusion provides you the capability to manage existing files on the application serverfile system through four action paramenters of the action attribute of the cffile tag:move, rename, copy, and delete.

The code in this technique provides an example of moving a file from one location(the source) to a new location (the destination).When using <cffile> with theaction attribute set to move, there are three required and four optional parameters.These parameters are described in detail in Table 10.6.

Table 10.6 Move Action cffile Attributes

Attribute Description

action Required. Must be set to move for a move action.

destination Required. Defines the absolute path destination for the moved file.Windows uses backslashes in the absolute path; UNIX systems use forwardslashes.

source Required. Defines the absolute path of the file you wish to move, includingthe filename.Windows uses backslashes in the absolute path; UNIX systemsuse forward slashes.

attributes Optional. List of attributes to set on the new file.

charset Optional. Defines the character set used to create the new file. Default isUTF-8.

mode Optional. Defines the permission set to UNIX files.

ColdFusion also provides you the capability to rename files on the application server filesystem through the action=”rename” setting on the <cffile> tag, as shown in thefollowing code:

<cfset myPath = “c:\documents\myfile.txt”>

<cfset myNewPath = “c:\documents\myfileRenamed.txt”>

<cfif FileExists(myPath)>

<cffile

action = “rename”

source = “#myPath#”

destination = “#myNewPath#”>

<cfoutput>File #myPath# renamed to #myNewPath#</cfoutput>

<cfelse>

<cfoutput>File #myPath# doesn’t exist!</cfoutput>

</cfif>

14 0672324628 CH10 6/8/05 11:08 AM Page 133

Page 157: ColdFusion MX Developer's Cookbook (Developer's Library)

134 Chapter 10 Files and Directories

The available attributes for renaming a file are identical to those for moving a file, exceptthere is no charset attribute.Also remember that the destination must contain the file-name for the renamed file in addition to the absolute path.

You can copy files on the application server file system through the action=”copy”setting on the <cffile> tag, as shown in the following code:

<cfset myPath = “c:\documents\myfile.txt”>

<cfset myNewPath = “c:\documents\myfileCopied.txt”>

<cfif FileExists(myPath)>

<cffile

action = “copy”

source = “#myPath#”

destination = “#myNewPath#”>

<cfoutput>File #myPath# copied to #myNewPath#</cfoutput>

<cfelse>

<cfoutput>File #myPath# doesn’t exist!</cfoutput>

</cfif>

The available attributes for copying a file are identical to those for renaming a file exceptthat the destination attribute can optionally supply a filename.

You can delete a file on the application server file system through theaction=”delete” setting on the <cffile> tag, as shown in the following code:

<cfset myPath = “c:\documents\myfile.txt”>

<cfif FileExists(myPath)>

<cffile

action = “delete”

file = “#myPath#”>

<cfoutput>File #myPath# deleted</cfoutput>

<cfelse>

<cfoutput>File #myPath# doesn’t exist!</cfoutput>

</cfif>

The action=”delete” setting on the <cffile> tag accepts only one attribute inaddition to action; file should contain the full absolute path of the file you want todelete.

10.6. Listing DirectoriesYou want to discover the contents of a directory on the application server filesystem.

TechniqueUse the <cfdirectory> tag to inspect the contents of a directory on the applicationserver file system.

<cfdirectory directory=”c:\” name=”getDirectory”>

14 0672324628 CH10 6/8/05 11:08 AM Page 134

Page 158: ColdFusion MX Developer's Cookbook (Developer's Library)

13510.6. Listing Directories

CommentsColdFusion provides you the capability to inspect the contents of a directory on theapplication server file system through the action=”list” setting on the <cfdirectory> tag.

When using <cfdirectory> with the action attribute set to “list”, there aretwo required and three optional parameters.These parameters are described in detail inTable 10.7.

Table 10.7 List Action cfdirectory Attributes

Attribute Description

action Optional because the default is list, this parameter must be left as the defaultor explicitly set to list for a list action.

directory Required.The absolute path of the directory whose contents you want to list.

filter Optional. File extension restriction for list of returned items.

name Required. ColdFusion variable name for returned query object.sort Optional. Comma-separated list of sorted columns and sort directions (asc or

desc) to place on the returned query object. Example:“columnName ASC”

Executing the list action with <cfdirectory> returns a query object containing sixcolumns: attributes, dateLastModified, mode, name, size, and type.

Attributes contains the file attributes, dateLastModified contains the datestring for the last modification of the item, mode contains the UNIX mode for the item(mode returns empty on Windows systems), name contains the name of the item, sizecontains the size of the item (directories return 0), and type returns dir for directoriesor file for files.

With the <cfdirectory> list action, it is simple to create a ColdFusion templatethat will return to the user a page displaying the contents of a directory.An example ofthis functionality is shown in the following code.

<cfparam name=”directory” default=”c:\”>

<cfdirectory

directory=”#directory#”

name=”getDirectory”

sort=”type, name”>

<cfoutput query=”getDirectory”>

<cfif type eq “dir”>

<cfset path = directory & name & “\”>

<a href=”./directory.cfm?directory=#path#”>#name#</a>

<cfelse>

#name#

</cfif>

<p>

</cfoutput>

14 0672324628 CH10 6/8/05 11:08 AM Page 135

Page 159: ColdFusion MX Developer's Cookbook (Developer's Library)

136 Chapter 10 Files and Directories

This example code provides a simple page allowing the user to traverse the applicationserver’s file system starting at the c:\ drive. If the type value for an item is dir, thecode builds a link to expand that directory. If the type value is file, it simply displaysthe name of the file. Save the previous code as directory.cfm on your machine andtry it for yourself.

10.7. Manipulating DirectoriesYou want to create, rename, or remove a directory on the application server filesystem.

TechniqueUse the <cfdirectory> tag to manipulate a directory on the application server filesystem.

<cfdirectory action=”create” directory=”c:\newdirectory”>

CommentsColdFusion provides you the capability to manipulate a directory on the applicationserver file system through the create, rename, and delete actions on the <cfdirectory> tag.

The code in the previous technique creates a new directory at the path c:\newdirectory. Save this code to your machine and execute it. Now rename the directory to newdirectoryTest using the following code:

<cfdirectory

action=”rename”

directory=”c:\newdirectory”

newDirectory=”c:\newdirectoryTest”>

The preceding code renames the directory c:\newdirectory toc:\newdirectoryTest. Save this code to your machine and execute it. Now deletethat directory with the following code:

<cfdirectory action=”delete” directory=”c:\newdirectoryTest”>

The preceding code deleted the directory located at c:\newdirecoryTest. Note thatonly empty directories can be deleted. If a directory contains files or other directories,and you attempt delete the directory using <cfdirectory>, ColdFusion will throw aNonEmptyDirectoryCannotBeDeletedException exception.

14 0672324628 CH10 6/8/05 11:08 AM Page 136

Page 160: ColdFusion MX Developer's Cookbook (Developer's Library)

11Using Internet Protocols

11.0. IntroductionColdFusion is an effective mediator for marshalling data in and out of different datarepositories. Its communication’s API is as broad as it is practical and easy to use.

ColdFusion’s Internet Protocol API rounds out its I/O library.A mere seven tagsallow you to leverage the most popular Internet protocols to enhance the capabilities ofyour ColdFusion application. In this chapter, you learn how to issue HTTP requests,send and receive email, query LDAP directories, and communicate with FTP servers.

11.1. HTTP RequestsYou want to issue a server-to-server HTTP request.

TechniqueUse the <cfhttp> tag to issue a simple HTTP request and inspect the results.

<cfset destination = “http://www.macromedia.com”><cfhttp url=”#destination#”>

</cfhttp>

<cfdump var=”#cfhttp#”>

CommentsThis technique involves using the <cfhttp> tag to connect to a URL. It then printsout the result for the users to see.

The <cfhttp> tag requires but a single attribute: url (see Table 11.1 for a completelisting of the allowed attributes for <cfhttp>).The tag connects to the URL, retrievesthe results from the server, stores them in a ColdFusion structure, and returns the results.

15 0672324628 CH11 6/8/05 11:08 AM Page 137

Page 161: ColdFusion MX Developer's Cookbook (Developer's Library)

138 Chapter 11 Using Internet Protocols

ColdFusion stores these results in a structure named cfhttp.This structure will containthe output of the HTTP request in its filecontent property.A number of other tid-bits of information are available to you as well (see Table 11.2 for a complete listing ofthe cfhttp structure), such as the MIME type, the status code, and the full responseheader sent by the Web server.

The current example uses the <cfdump> tag to display the contents of the cfhttpstructure to the users.This is an effective way to examine the breadth of information andmetadata that ColdFusion provides to you about an HTTP request.

Table 11.1 <cfhttp> Syntax

Attribute Value

Url Required.The absolute URL of the document to be retrieved.TheURL must include the protocol (http or https) and the hostname. It may or may not include the port. Default: http.

Port Optional.The port number that should be used when issuing theHTTP request.Any port specified in the URL string (for example,http://hostname:port/) takes priority over this argument.Default: 80.

Method Optional.The method to use when issuing the request. Get can beused to retrieve any type of document. Post should be used whenposting form data to a CGI program.The <cfhttpparam> tagmust be used with the Post option. Default: get.

Username Optional.The username to be used when requesting a secured doc-ument.

Password Optional.The password to be used when requesting a secured doc-ument.

Name Optional.The name to be assigned to a query constructed out ofthe results of a call to <cfhttp>.

Columns Optional. Used when creating a query out of a text documentdownloaded using the Get option.This attribute specifies the col-umn names to use for the different fields. Leave this option blank ifthe first row in the text document defines the column names.

FirstRowAsHeaders Optional. If the columns attribute is unspecified, the first row ofdata in the text file will be used to determine the column namesfor the query.

Path Optional.The path to a directory in which to store the result of theHTTP request.A cfhttp.filecontent variable is created if thisattribute is not specified.

File Optional (required if Path and Post options are specified).Thefilename to use when saving the result of the HTTP request.Youmust specify this variable when using the Post method option.

Delimiter Optional.The delimiter to use when creating a query out of theresult document. Default: comma.

15 0672324628 CH11 6/8/05 11:08 AM Page 138

Page 162: ColdFusion MX Developer's Cookbook (Developer's Library)

13911.1. HTTP Requests

TextQualifier Optional.The text qualifier (if any) to be used when parsing theresult document to create a query. Default: “”.

ResolveURL Optional.When this option is set to “Yes”, ColdFusion willresolve all URLs in the result document so that the links remainintact. Specifically, ColdFusion will insert the protocol, host name,and port into all embedded references. Default: No.

ProxyServer Optional. Host name or IP address of a proxy server (if any) con-trolling outbound HTTP requests.

ProxyPort Optional.The port to be used when issuing an HTTP request to aproxy server. Default: 80.

UserAgent Optional.The user agent request header to be sent to the Webserver.

ThrowOnError Optional.This specifies whether ColdFusion should throw an errorif the document cannot be retrieved. If set to “Yes”, <cftry> and<cfcatch> should be used to handle the error. Default: No.

Redirect Optional.This specifies whether ColdFusion should follow a redi-rect request from the Web server. If set to “No”, you can use thecfhttp.responseHeader.LOCATION variable to determinewhether a redirect request was issued. Default: Yes.

Timeout Optional.The amount of time, in seconds, the ColdFusion servershould wait for an HTTP request to return. ColdFusion will usethe lesser of this attribute and the Administrator timeout. If neitherare specified, ColdFusion will wait indefinitely for the request toterminate.

Charset Optional.A Java character set for the file or URL in an HTTPrequest. Default: UTF-8.

Table 11.2 cfhttp Response Variable

Key Value

cfhttp.filecontent The content of the HTTP response, for text and MME filesonly.

cfhttp.mimeType The MIME type of the response (for example,“text/html”).

cfhttp.responseHeader A CFML data structure representing the response headersreturned from the Web server. Most often, this variable will bea structure with multiple keys (one key per header variable).

cfhttp.header The raw response header text.cfhttp.statuscode The HTTP error code and message string.

Table 11.1 Continued

Attribute Value

15 0672324628 CH11 6/8/05 11:08 AM Page 139

Page 163: ColdFusion MX Developer's Cookbook (Developer's Library)

140 Chapter 11 Using Internet Protocols

11.2. Sending EmailYou want your ColdFusion page to send an email message to one or morepeople.

TechniqueUse the <cfmail> tag to send a text email.

<cfparam name=”emailaddress” default=”[email protected]”>

<cfmail to=”#emailaddress#”

from=”[email protected]

subject=”Test email message”

MIMEAttach=”#GetCurrentTemplatePath()#”>

The attached document contains the source code for this ColdFusion MX template.

</cfmail>

CommentsIn this example, the ColdFusion template checks for a submitted email address and usesthe <cfmail> tag to send a one-line email message back to the users.

This example requires that a valid SMTP mail server has been configured in theColdFusion administrator and ColdFusion will throw an exception if no such server ispresent. However, you can use the optional server attribute to specify a mail server atruntime.

The required <cfmail> attributes are to, the recipient’s email address; from, thesender’s email address; and subject, the subject of the message.The <cfmail> tag alsoaccepts many optional (but useful) attributes, including cc and bcc, a list of addresses tocarbon copy or blind carbon copy the message; type, which can specify text or HTMLcontent; and MIMEAttach, a server-based path to a file that should be attached to theemail.

11.3. Receiving EmailYou want your ColdFusion page to check for email on a mail server.

TechniqueUse the <cfpop> tag to connect to a POP server and download email messages.

<cfparam name=”popserver” default=”mail.mydomain.com”>

<cfparam name=”username” default=”myusername”>

<cfparam name=”password” default=”mypassword”>

15 0672324628 CH11 6/8/05 11:08 AM Page 140

Page 164: ColdFusion MX Developer's Cookbook (Developer's Library)

14111.4. Querying an LDAP Directory

<cfpop server=”#popserver#”

username=”#username#”

password=”#password#”

action=”getAll”

name=”emailquery”

maxrows=”10”>

<cfdump var=”#emailquery#”>

CommentsThis example gathers the minimum amount of information from the users in order toconnect to a POP server and download some messages.The template expects the follow-ing three variables: popserver, username, and password.The popserver should bethe host name or IP address of an available POP server on which the user has anaccount.The username and password variables should, naturally, contain the usernameand password for the user’s account.

The ColdFusion template uses the <cfpop> tag to pull 10 messages (specified by themaxrows attribute) off of the POP server.The action attribute accepts three possiblevalues: getHeaderOnly, getAll, and delete.The getHeaderOnly option willforce the tag to return only the email headers.This will take less time and is the bestoption to use when displaying a summary listing of email messages.

The getAll option causes the entire email message body and any attachments (inaddition to the header) to be returned to the calling template.This option is best used todisplay a detailed view for a smaller number of messages.

The delete action will delete one or more messages from the POP server.Whenusing this action, you must also set the messageNumber attribute.This attribute con-tains one or more message IDs to be deleted.You should note that to delete a message,you must make two calls to <cfpop>: one call to retrieve the headers and message IDsand a second to actually delete the messages.

11.4. Querying an LDAP DirectoryYou want to query an LDAP directory for use in your page.

TechniqueUse the <cfldap> tag to query an LDAP directory.

<cfparam name=”ldapserver” default=”ldap.mydomain.com”>

<cfparam name=”username” default=”myusername”>

<cfparam name=”password” default=”mypassword”>

<cfparam name=”filter” default=””>

<cfparam name=”attributes” default=””>

15 0672324628 CH11 6/8/05 11:08 AM Page 141

Page 165: ColdFusion MX Developer's Cookbook (Developer's Library)

142 Chapter 11 Using Internet Protocols

<cfparam name=”start” default=””>

<cfldap server=”#ldapserver#”

action=”query”

username=”#username#”

password=”#password#”

start=”#start#”

filter=”#filter#”

attributes=”#attributes#”

name=”ldapquery”>

<cfdump var=”#ldapquery#”>

CommentsThe Lightweight Directory Access Protocol (LDAP) was invented in 1995 at theUniversity of Michigan.The protocol was designed to provide access to online directo-ries over TCP/IP. LDAP was a lightweight replacement for the DAP (Directory AccessProtocol), which served information housed in OSI X.500-compliant directory servers.LDAP has since found its way into countless back offices, providing access to directoriesof users, email services, organizational units, and many other types of information.

LDAP directories organize the information they contain in a hierarchy. Each elementin the tree is assigned a distinguished name (DN) that uniquely identifies it in the direc-tory.The DN is comprised of the element’s relative distinguished name (RDN) and theRDN of its parents. For example, a computer called “computer1” might be given theRDN, “CN=computer1”.This name would uniquely identify the element in the con-text of its parent container. If the computer belonged to the sales department of thecompany “mycompany.com”, its DN might be “CN=computer1, OU=sales,DC=mycompany, DC=com”.The computer would also have the following canonicalname: “mycompany.com/sales/computer1”.

LDAP queries all have a few things in common. First, they all begin their searches at abase DN.This could be the top of the tree (for example, “DC=mycompany, DC=com”)or any other node in the tree. Second, LDAP queries usually have one or more filters tonarrow the search. LDAP filters use a prefix format in their syntax. For example, the fil-ter “(&(l=Raleigh)(st=North Carolina))” would find all directory entries witha location of “Raleigh” and a state of “North Carolina”. Finally, an LDAP queryusually specifies a list of attributes to return.Attributes are the different fields that anLDAP entry contains.The values that these attributes contain can be stored on the entryor derived by some other means.Attribute names are specific to the type of LDAP entryto which they belong.

The example in this section uses the <cfldap> tag with its action attribute set to“query” to perform a query against a user-specified LDAP database.You must definethe following attributes in the <cfldap> tag when executing a query: server (the

15 0672324628 CH11 6/8/05 11:08 AM Page 142

Page 166: ColdFusion MX Developer's Cookbook (Developer's Library)

14311.5. Adding an LDAP Entry

name or IP address of the LDAP server), username (the username of a user authorizedto perform the query), password (the user’s password), start (the starting DN wherethe query will begin), filter (the filter test to be applied to all nodes in the searchscope), attributes (the LDAP attributes to be returned from the query), and name(the name of the ColdFusion query object that will house the results).

11.5. Adding an LDAP EntryYou want to add an entry to an LDAP directory.

TechniqueUse the <cfldap> tag with its action attribute set to “add” to add a new entry to anLDAP server.

<cfparam name=”dn” default=”CN=jsmith,OU=Departments,DC=mycompany,DC=com”>

<cfparam name=”username” default=”jsmith”>

<cfparam name=”firstName” default=”John”>

<cfparam name=”lastName” default=”Smith”>

<cfparam name=”displayName” default=”John Smith”>

<cfparam name=”city” default=”Raleigh”>

<cfparam name=”state” default=”North Carolina”>

<cfparam name=”email” default=”[email protected]”>

<cfparam name=”username” default=”[email protected]”>

<cfparam name=”password” default=”password”>

<cfparam name=”ldapserver” default=”ldap1.mycompany.com”>

<cfset attributelist = “objectclass=top, person, organizationalPerson, user;”>

<cfset attributelist = attributelist&

“cn=#Trim(displayName)#;givenName=#firstName#; sn=#lastName#;”>

<cfset attributelist = attributelist&”l=#city#;st=#state#;mail=#email#”>

<cftry>

<cfldap action=”add”

attributes=”#attributelist#”

dn=”#dn#”

server=”#ldapserver#”

username=”#username#”

password=”#password#”>

<cfcatch>

<cfdump var=”#cfcatch#”>

</cfcatch>

</cftry>

15 0672324628 CH11 6/8/05 11:08 AM Page 143

Page 167: ColdFusion MX Developer's Cookbook (Developer's Library)

CommentsThis example uses the <cfldap> tag to add a new entry to the LDAP directory byassigning the value “add” to the tag’s action attribute and providing the necessaryinformation to create the new entry.The example catches any exceptions that might bethrown by the LDAP request, such as a connection failure or an authentication failure.

To add a new entry, you must also provide the following attributes: attributes (asemicolon-delimited list of attribute name/value pairs), dn (the distinguished name toassign the new entry), server (the name or IP address of the LDAP server), username(the username of a user who is authorized to perform this transaction), and password(the authorized user’s password).

Take care that you specify all of the required attributes for the type of entry that youare adding. Consult your LDAP server’s documentation to determine the required attrib-utes.

11.6. Updating an LDAP EntryYou want to update an existing entry in an LDAP directory.

TechniqueUse the <cfldap> tag with its action attribute set to ”modify” to update an existingentry on an LDAP server.

<cfparam name=”dn” default=”CN=John Smith,OU=Departments,DC=mycompany,DC=com”>

<cfparam name=”username” default=”[email protected]”>

<cfparam name=”password” default=”password”>

<cfparam name=”ldapserver” default=”ldap1.mycompany.com”>

<cfset attributelist = “title=VP of Product Development”>

<cftry>

<cfldap action=”modify”

modifytype=”replace”

attributes=”#attributelist#”

dn=”#dn#”

server=”#ldapserver#”

username=”#username#”

password=”#password#”>

<cfcatch>

<cfdump var=”#cfcatch#”>

</cfcatch>

</cftry>

144 Chapter 11 Using Internet Protocols

15 0672324628 CH11 6/8/05 11:08 AM Page 144

Page 168: ColdFusion MX Developer's Cookbook (Developer's Library)

14511.7. Adding and Deleting an LDAP Entry’s Attributes

CommentsThis example updates an existing attribute on an existing LDAP entry. Specifically, it setsJohn Smith’s title to “VP of Product Development.”To perform this operation, you mustspecify the following <cfldap> attributes: action (must be set to “modify”),modifytype (what to do with the specified attributes in the case of a multi-valuedattribute: “add”, “delete”, or “replace”), attributes (a semicolon-delimited listof attribute name/value pairs to be updated on the entry), server (the name or IPaddress of the LDAP server), username (the username of an authorized user), andpassword (the user’s password).

11.7. Adding and Deleting an LDAP Entry’sAttributes

You want to add or delete attributes on an existing LDAP entry.

TechniqueUse the <cfldap> tag with its action attribute set to “modify” to add or delete anattribute on an LDAP entry.

<cfparam name=”dn” default=”CN=John Smith,OU=Departments,DC=mycompany,DC=com”>

<cfparam name=”username” default=”[email protected]”>

<cfparam name=”password” default=”password”>

<cfparam name=”ldapserver” default=”ldap1.mycompany.com”>

<cfset attributelist = “title=VP of Product Development”>

<cftry>

<cfldap action=”modify”

modifytype=”add”

attributes=”#attributelist#”

dn=”#dn#”

server=”#ldapserver#”

username=”#username#”

password=”#password#”>

<cfcatch>

<cfdump var=”#cfcatch#”>

</cfcatch>

</cftry>

15 0672324628 CH11 6/8/05 11:08 AM Page 145

Page 169: ColdFusion MX Developer's Cookbook (Developer's Library)

146 Chapter 11 Using Internet Protocols

CommentsThe technique you use to add or delete an attribute is almost identical to how youupdate an attribute.The only difference is the value of the modifytype attribute in the<cfldap> tag. Setting the attribute to “add” will add the specified attributes if they donot exist. Conversely, setting the attribute to “delete” will remove the attributes fromthe entry.

11.8. Renaming an EntryYou want to change the distinguished name of an LDAP entry.

TechniqueUse the <cfldap> tag with its action attribute set to ”modifyDN” to change anLDAP entry’s distinguished name.

<cfparam name=”olddn”

default=”CN=John Smith,OU=Departments,DC=mycompany,DC=com”>

<cfset attributelist =

“dn=CN=John C. Smith, OU=Departments, DC=mycompany, DC=com”>

<cftry>

<cfldap action=”modifyDN”

attributes=”#attributelist#”

dn=”#dn#”

server=”#ldapserver#”

username=”#username#”

password=”#password#”>

<cfcatch>

<cfdump var=”#cfcatch#”>

</cfcatch>

</cftry>

CommentsTo rename an LDAP entry, you set the <cfldap> tag’s action attribute to“modifyDN”.The rest of the <cfldap> attributes are the same as when updating anentry’s attribute; only the attributes attribute specifies the item’s new distinguishedname.

15 0672324628 CH11 6/8/05 11:08 AM Page 146

Page 170: ColdFusion MX Developer's Cookbook (Developer's Library)

14711.10. Sending a File via FTP

11.9. Deleting an LDAP EntryYou want to delete an entry from an LDAP directory.

TechniqueUse the <cfldap> tag with its action attribute set to “delete” to remove an entryfrom an LDAP directory.

<cfparam name=”dn” default=”CN=John Smith,OU=Departments,DC=mycompany,DC=com”>

<cftry>

<cfldap action=”delete”

dn=”#dn#”

server=”#ldapserver#”

username=”#username#”

password=”#password#”>

<cfcatch>

<cfdump var=”#cfcatch#”>

</cfcatch>

</cftry>

CommentsDeleting an LDAP entry is really easy; just set the action attribute to “delete” andspecify the DN of the item to delete via the <cfldap> dn attribute. Once again, theusual suspects—server, username, and password—are in attendance.

11.10. Sending a File via FTPYou want to upload a file from the ColdFusion server to an FTP server.

TechniqueUse the <cfftp> tag to move a file up to an FTP server.

<cfparam name=”username” default=”myusername”>

<cfparam name=”password” default=”mypassword”>

<cfparam name=”ftpserver” default=”ftp.mydomain.com”>

<cfparam name=”localfile” default=”/myfile.txt”>

<cfparam name=”remotefile” default=”/myfile.txt”>

<cfftp action=”putfile”

username=”#username#”

15 0672324628 CH11 6/8/05 11:08 AM Page 147

Page 171: ColdFusion MX Developer's Cookbook (Developer's Library)

148 Chapter 11 Using Internet Protocols

password=”#password#”

server=”#ftpserver#”

localfile=”#localfile#”

remotefile=”#remotefile#”>

<cfdump var=”#cfftp#”>

CommentsColdFusion MX provides FTP support with its <cfftp> tag.The tag can be used toperform any of the various FTP commands that can be executed from a commandprompt, including uploading files, downloading files, creating directories, and listingdirectories. Like the <cfldap> tag, the <cfftp> tag relies on its action attribute todictate its behavior.

In most cases, <cfftp> creates a connection to the FTP server, performs the request-ed action, closes the connection, and returns the results of the command to the userusing the cfftp.returnValue variable.

This behavior can be undesirable if you need to perform multiple commands on thesame FTP server. In such cases, ColdFusion allows you to cache FTP connections. Byusing the “open” action, you can create a persistent connection to an FTP server andsave the handle in a ColdFusion variable. Subsequent calls to <cfftp> can re-use thisconnection via the tag’s connection attribute.When you are finished using the FTPconnection, you can close it with a final call to <cfftp> using the “close” action.

In this example, you do not need to use connection caching because you just need toperform a single FTP operation—uploading a file to an FTP server.The “putfile”action requires the following attributes to be set: username (the username to use whenconnecting the FTP server), password (the password to use when connecting), server(the name or IP address of the FTP server), localfile (the full path description of thefile to be sent), and remotefile (the name of the file to create on the server).

11.11. Getting a File via FTPYou want to download a file from an FTP server.

TechniqueUse the <cfftp> tag to download a file from an FTP server.

<cfparam name=”username”

<cfparam name=”password”

<cfparam name=”ftpserver”

<cfparam name=”localfile”

<cfparam name=”remotefile”

15 0672324628 CH11 6/8/05 11:09 AM Page 148

Page 172: ColdFusion MX Developer's Cookbook (Developer's Library)

14911.11. Getting a File via FTP

<cfftp action=”getfile”

username=”#username#”

password=”#password#”

server=”#ftpserver#”

localfile=”#localfile#”

remotefile=”#remotefile#”>

<cfdump var=”#cfftp#”>

CommentsDownloading a file from an FTP server is very similar to uploading one.The actionattribute must be set to “getFile”.The rest of the arguments are the same; only theremotefile attribute now represents the file to be retrieved and the localfile

attribute represents the file to be created.

15 0672324628 CH11 6/8/05 11:09 AM Page 149

Page 173: ColdFusion MX Developer's Cookbook (Developer's Library)

15 0672324628 CH11 6/8/05 11:09 AM Page 150

Page 174: ColdFusion MX Developer's Cookbook (Developer's Library)

12Using Verity

12.0. IntroductionOne common component of easy-to-use Web applications is a search interface.As theamount of pure content grows in a Web application, searching tools become more criti-cal.Thankfully, ColdFusion includes a simple interface into one of the most powerfulsearch engines on the market, Verity.Verity ships with ColdFusion MX and can be usedwith relative ease by a developer with limited Verity knowledge.

This chapter is simply an introduction to the Verity Search Engine and the associatedtools ColdFusion provides.Verity is a complex, mature searching tool. If you do not findthe information in this chapter sufficient to solve your search-engine development, youcan find more information at the original manufacturers’s Web site: http://www.verity.com.

12.1. Creating a CollectionYou want to create a Verity collection and define its properties.

TechniqueUse the <cfcollection> tag or the ColdFusion Administrator to create a Verity col-lection.

<cfcollection action=”Create”

collection=”myCollection”

path=”c:\cfusionmx\collections\”>

16 0672324628 CH12 6/8/05 11:09 AM Page 151

Page 175: ColdFusion MX Developer's Cookbook (Developer's Library)

152 Chapter 12 Using Verity

CommentsThere are two ways to create a Verity collection. One way is to use the <cfcollection> tag as is shown in the previous technique.When used to create a collection, the <cfcollection> tag accepts one optional and three required attributes.These attributes are defined in Table 12.1.

Table 12.1 cfcollection Create Task Attributes

Attribute Description

action Required. Must be create to create a collection.

collection Required. String name of the collection you want to create.

path Required. Defines the absolute path to the directory where you want to storethe collection.

language Optional. Defines the locale used to index the collection.You must have theVerity Locale Language Pack installed for the Locale you plan to use. Defaultis English.

You can also create a new Verity collection using the ColdFusion Administrator.To doso, log into the administrator and browse to the Verity Collections page under Data &Services.This page presents a form to create new collections. Simply enter the name ofyour new collection, change the path or accept the default, and click Submit.

12.2. Adding Information to a VerityCollection

You want to add information to a Verity collection.

TechniqueUse the <cfindex> tag or the ColdFusion Administrator to add data to a Verity collec-tion.

<cfindex

collection=”myCollection”

action=”update”

type=”file”

key=”c:\inetpub\wwwroot\index.html”

urlPath=”http://localhost/”>

CommentsThere are two ways to add data to an existing Verity collection. One way is to use the<cfindex> tag as is shown in the previous technique.When used to add data to a

16 0672324628 CH12 6/8/05 11:09 AM Page 152

Page 176: ColdFusion MX Developer's Cookbook (Developer's Library)

15312.2. Adding Information to a Verity Collection

collection, the <cfindex> tag behaves differently depending on whether you want toadd a single file to the collection, all files contained in a directory (and optionally, itssub-directories), or data contained in a query set.These attributes are defined in Table 12.2.

Table 12.2 cfindex Update Task Attributes

Attribute Description

action Required. Must be update to add data to a collection.

body Required only if type is custom. Defines the query columns containing thedata you want to add to the collection as a comma-delimited list.

collection Required. String name of the collection to which you want to add data.

extensions Optional. Defines an extension filter to use when type is set to path.ColdFusion will only update the collection with data from files that satisfythe extension criteria. Default is“.cfm,.cfml,.dbm,.dbml,.htm,.html”.

key Optional. Defines the absolute path to the desired file if the type attribute isset to file. Defines the absolute path to the desired directory if type is setto path. Defines the name of the column used for the key if type is set tocustom. Default is an empty string.

language Optional. Defines the locale used to index the collection.You must have theVerity Locale Language Pack installed for the Locale you plan to use. Defaultis English.

query Required if type is set to custom. Defines the name of the query contain-ing the data used to update the collection.

recurse Optional.Applies only if type is set to path. Determines whether subdirec-tories of the path defined should be included in the collection. Default is No.

type Optional.Accepted values are file, path, and custom. If file is specified,this attribute updates the collection with data in the file defined by the keyattribute. If path is specified, this attribute updates the collection with datafrom files in the path defined by the key attribute. If custom is specified, thisattribute updates the collection with data specified by the key column of theprovided query. Default is custom if query is provided, file otherwise.

urlPath Optional. Defines the URL path for retrieving the desired items to bereturned from a <cfsearch> execution.

There are numerous methods to add data to an existing collection.To add a single file tothe collection, take a look at the following code example:

<cfindex

collection=”myCollection”

action=”update”

type=”file”

key=”c:\documents\someFile.txt”>

16 0672324628 CH12 6/8/05 11:09 AM Page 153

Page 177: ColdFusion MX Developer's Cookbook (Developer's Library)

154 Chapter 12 Using Verity

This example adds the content in file c:\documents\someFile.txt to the existingmyCollectionVerity collection.The action is set to update, as is the case whenadding any type of data to a collection.The type is set to file, which alertsColdFusion that this update will take place only on a specific file.The key field then isused to define the absolute path to the desired file.

You can also add data from all files in a directory and a sub-directory to a Verity collection.To add content from a hierarchy of directories, take a look at the followingexample:

<cfindex

collection=”myCollection”

action=”update”

type=”path”

key=”c:\documents”

recurse=”yes”

extensions=”.pdf,.txt”>

This example adds all the documents found in the directory structure beneath c:\documents that satisfy the extensions filter to the myCollectionVerity collection.Because the type is path, the key attribute defines the absolute path to the parentdirectory. Recurse is set to yes to instruct ColdFusion to recurse through the directorystructure found beneath the directory defined by the key attribute.The extensions filteris also used to define the file types to be included in the collection. Notice that one ofthe file types is .PDF—Acrobat documents are supported in Verity collections.

You can also add data from a query record set to a Verity collection.To add data to aVerity collection using the results of a query, take a look at the following example:

<cfquery

name=”getContent”

datasource=”myDS”>

SELECT id,content

FROM myTable

</cfquery>

<cfindex

collection=”myCollection”

action=”update”

type=”custom”

body=”content”

key=”id”

query=”getContent”>

This example adds data from the content field into the myCollectionsVerity collec-tion.The type is defined as custom, which is required when using a query object asinput.The body attribute defines which column or columns contain the data you want

16 0672324628 CH12 6/8/05 11:09 AM Page 154

Page 178: ColdFusion MX Developer's Cookbook (Developer's Library)

15512.3. Searching a Verity Collection with Simple Search

to add to the collection. Multiple column names should be delimited by commas.Thekey defines the column used to create the key; the best practice is to use the primarykey defined for the table.The query attribute simply defines the name of the queryused to populate the collection.

The refresh action can also be used to update an index, but it will delete all theexisting keys before adding the new content. In all the code examples in this section,refresh can be used as the type attribute instead of update.

You can also add content to an existing Verity collection using the ColdFusionAdministrator.To do so, log into the Administrator and browse to the Verity Collectionspage under Data & Services.This page lists all the existing Verity collections on the serv-er. Click the link displaying the name of the collection you want to update.This presentsa form allowing you to browse for a directory, define whether the update should includesubdirectories of the parent, define a file extension filter, and define a return URL.Afteryou fill in the appropriate form fields and click Submit, your collection is updated.

Another added benefit of the ColdFusion <cfindex> tag is the capability to addcustom fields to collection entries. <cfindex> allows up to two custom fields perrecord.The following code example adds the variables appName and username to thenew collection entry:

<cfindex

collection=”myCollection”

action=”update”

type=”file”

key=”c:\documents\someFile.txt”

custom1=”#appName#”

custom2=”#username#”>

12.3. Searching a Verity Collection with SimpleSearch

You want to perform a simple search against an existing Verity collection.

TechniqueUse the <cfsearch> tag with the type attribute set to simple to perform a simplesearch against an existing Verity collection.

<cfsearch

name = “collectionSearch”

collection = “myCollection”

criteria = “test”

type=”simple”>

16 0672324628 CH12 6/8/05 11:09 AM Page 155

Page 179: ColdFusion MX Developer's Cookbook (Developer's Library)

156 Chapter 12 Using Verity

CommentsThere are two types of search methods you can use against Verity collections: simple andexplicit.To perform a simple search against a collection, use the <cfsearch> tag withthe type attribute set to simple.The previous technique performs a simple searchagainst the myCollection collection for any entries containing the string test.

When used as a simple search, the <cfsearch> tag accepts two required and fiveoptional attributes.These attributes are defined in Table 12.3.

Table 12.3 cfsearch Attributes

Attribute Description

collection Required. Comma-delimited list of registered collection names or absolutepaths to other collections to include in the search.

criteria Optional. Defines the criteria used for the search. If left blank, all rows arereturned following the startRow.

language Optional. Defines the locale used to index the collection.You must have theVerity Locale Language Pack installed for the Locale you plan to use. Defaultis English.

maxRows Optional. Defines the maximum number of records to return in the search.

name Required. Defines the name of the query object returned from the searchexecution.

startRow Optional. Defines the first record number to retrieve. Usually used in combi-nation with maxRows.

type Required. Must be set to simple to perform a simple search.

A simple search will suffice for the majority of search tools. Simple search implies aSTEM operator, meaning that searches for the word test will return records containingthe words test, tests, tested, and testing. Note that STEM does not work on word frag-ments—that is, searching for tes will not function the same as searching for test.You can,however, use a wildcard character (*) to return the same results with tes. (This searchwould also return records containing the word testimony.)

Executing the <cfsearch> tag returns a query object containing one row per itemin the collection matching your search criteria and satisfying your extensions filter. Formore on ColdFusion query objects, see Chapter 5,“Queries.”

The returned query object contains eight columns.These columns are defined inTable 12.4.

Table 12.4 cfsearch Returned Query Object

Attribute Description

custom1 The value of the custom1 field for this record. If it’s not defined, anempty string is returned.

custom2 The value of the custom1 field for this record. If it’s not defined, anempty string is returned.

16 0672324628 CH12 6/8/05 11:09 AM Page 156

Page 180: ColdFusion MX Developer's Cookbook (Developer's Library)

15712.4. Searching a Verity Collection with Explicit Search

key The key value defined for the entry in the index.

recordsSearched The number of records searched in the collection.

score The Verity score for the record based on the search criteria.A perfectmatch gets a score of 1.

summary The content searched for this record.

title The value of the title property for the record. If it’s undefined, anempty string is returned.

url The value of the URL property for the record. If it’s undefined, anempty string is returned.

12.4. Searching a Verity Collection withExplicit Search

You want to perform an explicit search against an existing Verity collection.

TechniqueUse the <cfsearch> tag with the type attribute set to explicit to perform anexplicit search against an existing Verity collection.

<cfsearch

name = “collectionSearch”

collection = “myCollection”

criteria = ‘“test”’

type=”explicit”>

CommentsExplicit searches differ from simple searches in that the STEM operator is not implied.To perform an explicit search, you wrap the search string in double quotation marks asshown in the previous technique. Executing the search in this technique will only returndocuments containing the literal string test. It will not return testing or tests as will thecode in the previous technique.

NoteSearch terms in mixed case will perform a case-sensitive search. Search terms in all lowercase will perform

a case-insensitive search.

Table 12.4 Continued

Attribute Description

16 0672324628 CH12 6/8/05 11:09 AM Page 157

Page 181: ColdFusion MX Developer's Cookbook (Developer's Library)

16 0672324628 CH12 6/8/05 11:09 AM Page 158

Page 182: ColdFusion MX Developer's Cookbook (Developer's Library)

13User Authentication and

Authorization

13.0. IntroductionNearly every application developed these days requires that the users log in and authen-ticate their identity before performing certain actions. Recognizing this commonrequirement, ColdFusion MX introduced a framework for building authentication andauthorization logic.

The authentication and authorization framework in ColdFusion is independent of theauthentication repository (sometimes called the authentication realm), which provides agreat deal of flexibility. In other words, it doesn’t matter where your usernames, pass-words, and other user data is stored—you could use a database, an LDAP directory, aKerberos repository, files,Web services, or anything you can access with ColdFusion.Youcan also build authentication that combines multiple repositories. In section 13.7,“Authentication Example,” you will build such an application.

The framework provides a new variable scope that allows the user credentials tocome from a number of sources, including a form variable, a URL variable, and HTTPbasic authentication.With this capability, the same code can be used to authenticate Webservices, Flash applications, mobile applications, or any Web application.

In addition to providing a flexible authentication framework, ColdFusion provides asimple yet robust authorization scheme using roles. Roles allow you to easily determinewhether a user has permission to perform a specific action.

17 0672324628 CH13 6/8/05 11:09 AM Page 159

Page 183: ColdFusion MX Developer's Cookbook (Developer's Library)

160 Chapter 13 User Authentication and Authorization

13.1. Logging in a UserYou want to tell ColdFusion that a user is logged in.

TechniqueUse the <cflogin> and <cfloginuser> tags to tell ColdFusion that a user haslogged in.

<cflogin>

<cfloginuser name=”anonymous” password=”guest” roles=”guest”>

Now reload this page, and you won’t see this message.

</cflogin>

CommentsThe <cflogin> tag is used to contain a block of code where the authentication logicresides.The best way to think about the <cflogin> tag is “If a user is not logged inthen run this code.”

The <cfloginuser> tag tells ColdFusion which user is logged in, and what actionsthey are allowed to perform (roles). ColdFusion uses its own type of built-in sessionvariables and non-persistent cookies to store this data.

NoteBecause the cflogin scope is different from the session scope, it is possible for your session scope to

expire before the cflogin scope. It is a good idea to set your session scope to have the same timeout as

your cflogin scope. You should also always validate that a session variable is defined before you attempt

to use it.

The first time you run this technique, the code inside the <cflogin> tags will execute,and your browser session will be “logged in.” Subsequent requests to the page will notdisplay the reload message; the <cflogin> code is skipped because you are alreadylogged in by the <cfloginuser> tag.

13.2. Logging out a UserYou want to tell ColdFusion to log out a user.

TechniqueUse the <cflogout> tag to log out a user.

<cflogout>

You have been logged out, please come again.

17 0672324628 CH13 6/8/05 11:09 AM Page 160

Page 184: ColdFusion MX Developer's Cookbook (Developer's Library)

16113.3. Authenticating a User

CommentsColdFusion will log a user out automatically when the browser is closed, or when theidleTimeout expires.The idleTimeout is an attribute of the <cflogin> tag; itdefaults to 1800 seconds (30 minutes).

It is often necessary to provide a mechanism that allows users to log out before theircflogin session expires.The <cflogout> tag provides such a mechanism.When it’sexecuted, ColdFusion clears the cflogin scope and the user is effectively logged out.

13.3. Authenticating a UserYou want to log in a user if the credentials are valid.

TechniqueUse the j_username and j_password form field names to authenticate a user.

<!--- if user is not logged in --->

<cflogin>

<cfset displayLoginForm = true>

<!--- if username and password present --->

<cfif IsDefined(“cflogin.name”) AND IsDefined(“cflogin.password”)>

<!--- if user and pass are authentic --->

<cfif cflogin.name is “pete” AND cflogin.password is “go”>

<!--- tell CF who they are, and what they can do --->

<cfloginuser name=”#cflogin.name#”

password=”#cflogin.password#” roles=”user”>

<!--- no need to display login form --->

<cfset displayLoginForm = false>

</cfif>

</cfif>

<cfif displayLoginForm>

<form method=”post”>

user: <input type=”text” name=”j_username”><br>

pass: <input type=”password” name=”j_password”><br>

<input type=”submit” value=”login”>

</form>

<cfabort>

</cfif>

</cflogin>

17 0672324628 CH13 6/8/05 11:09 AM Page 161

Page 185: ColdFusion MX Developer's Cookbook (Developer's Library)

162 Chapter 13 User Authentication and Authorization

CommentsThis technique determines whether a username and password was submitted to the page.If the credentials authenticate, the user is logged in; otherwise, the login form is dis-played.

The field names in the login form have a special meaning to ColdFusion.When aform is submitted with the field names j_username and j_password, ColdFusionautomatically populates the variables cflogin.name and cflogin.password withtheir respective values.Although you can simply use form.j_username and form.j_password to access the value of the username and password, using the cflogin scope enables you to use the same authentication code for URL variables orbasic HTTP authentication.

If you want to restrict access to every page in your application, theapplication.cfm file is an ideal place to implement <cflogin> logic, because it isimplicitly executed before every page request, including when CFCs are invoked as Webservices.

13.4. Obtaining the Logged-in User IDYou want to determine the user ID of the currently logged in user.

Technique Use the GetAuthUser function to get the user ID of the currently authenticated user.

<cflogin>

<cfloginuser name=”pete” password=”go” roles=”user”>

</cflogin>

<cfoutput>#GetAuthUser()#</cfoutput> is cool!

CommentsThe function GetAuthUser returns the value passed in to the name attribute of the<cfloginuser> tag.The function returns an empty string if the client is not authenti-cated.

13.5. Authorizing a Block of CodeYou want to ensure that only users in a specific role can execute a block ofcode.

TechniqueUse the IsUserInRole function to limit the blocks of code that users are allowed toexecute.

17 0672324628 CH13 6/8/05 11:09 AM Page 162

Page 186: ColdFusion MX Developer's Cookbook (Developer's Library)

16313.5. Authorizing a Block of Code

<cflogin>

<cfloginuser name=”pete” password=”go” roles=”user,admin”>

</cflogin>

<cfif IsUserInRole(“user”)>

In role: user

<cfelse>

Not in role: user

</cfif>

<cfif IsUserInRole(“admin”)>

In role: admin

<cfelse>

Not in role: admin

</cfif>

CommentsThe IsUserInRole function returns true or false depending on whether the currentlylogged in user is in the role passed into the function.

Recall that when you invoke the <cfloginuser> tag, you pass a comma-delimitedlist of role names into the roles attribute.The IsUserInRole function determines itsresult by using the list of roles passed in to the <cfloginuser> tag.

Roles tell the application which actions the user can perform. Roles are also knownas groups in some security policies.

An example of where you can find roles-based security is in a bank.At a basic level, abank’s employees can be broken into two groups: tellers and account managers.Tellerscan make deposits to and withdrawals from a bank account.Account managers can doanything that a teller can do, but also have added permissions to create and closeaccounts.

Even with this simple example, there are several ways to assign the roles. One possi-bility is to create two roles: one called tellers and the other called account_man-agers.Another possibility is to create a role for each privileged action.The roles may becalled deposit, withdraw, createAccount, and closeAccount.Then, each userwould be assigned multiple roles.

The roles you define are key to the flexibility and complexity of your authorizationsystem.When you define roles to job titles and then the job descriptions change, youhave to change your code. If you define roles to each action, you can end up with a toomany roles, which can be complex to handle. Because of this tradeoff between complex-ity and flexibility, it’s worth spending the time in your design process to contemplateyour particular situation before you define the roles.

17 0672324628 CH13 6/8/05 11:09 AM Page 163

Page 187: ColdFusion MX Developer's Cookbook (Developer's Library)

164 Chapter 13 User Authentication and Authorization

13.6. Authorizing a FunctionYou want to ensure that only users in a specific role can execute a particularfunction.

TechniqueUse the roles attribute of the <cffunction> tag to specify which roles can execute thefunction.

<cflogin>

<cfloginuser name=”pete” password=”go” roles=”user,admin”>

</cflogin>

<cffunction name=”userFunc” roles=”user,admin”>

<cfoutput>#GetAuthUser()# has permission to execute userFunc</cfoutput>

</cffunction>

<cffunction name=”adminOnly” roles=”admin”>

<cfoutput>#GetAuthUser()# has permission to execute adminOnly</cfoutput>

</cffunction>

<cfoutput>

#userFunc()#<br>

#adminOnly()#

</cfoutput>

CommentsRoles security can be implemented with the <cffunction> tag through eitherColdFusion components (see Chapter 19,“Components,” for more information onCFCs) or user-defined functions (see Chapter 16,“User-Defined Functions,” for moreinformation on UDFs).The <cffunction> tag has an attribute called roles thatallows you to specify a comma-delimited list of roles that have permission to execute thefunction.

<cffunction> will throw an exception if the user does not have permission to exe-cute the function.The error message generated by <cffunction> when a user is not inthe list of roles is not typically one you want to show to your users. Consider using<cftry>, <cfcatch>, or <cferror> to catch the exception. See Chapter 8,“Exception Handling,” for more information on dealing with these errors.

NoteThe documentation for ColdFusion MX specifies that the roles attribute of the <cffunction> can only

be used when <cffunction> is used in a ColdFusion component. This is not the case—it can be used in

a UDF as proven by the example in this technique. Because the actual intent of Macromedia may be differ-

ent from how it currently works, take note of this issue in future releases.

17 0672324628 CH13 6/8/05 11:09 AM Page 164

Page 188: ColdFusion MX Developer's Cookbook (Developer's Library)

13.7. Authentication ExampleYou want to authenticate multiple users against multiple repositories.

TechniqueUse an abstract component and inheritance to build an authentication architecture thatcan handle multiple users and repositories.

application.cfm:<cfapplication name=”acmeintranet” sessionmanagement=”yes”>

<!--- variable for datasource name --->

<cfset request.dsn = “cfcookbook”>

<cflogin>

<cfset authType = “Simple,Database,LDAP”>

<cfinclude template=”loginLogic.cfm”>

</cflogin>

loginLogic.cfm:<!--- if user is not logged in --->

<!--- if username and password present --->

<cfif IsDefined(“cflogin.name”) AND IsDefined(“cflogin.password”)>

<cfset loggedIn = false>

<!--- loop through the list of authorization

types (e.g. ldap, database, etc) --->

<cfloop list=”#authType#” index=”theAuthType”>

<cfset authenticator =

CreateObject(“component”, “#theAuthType#Authenticator”)>

<cfset loggedIn =

authenticator.authenticate(cflogin.name, cflogin.password)>

<cfif loggedIn is true>

<cfset session.user = authenticator.getUser()>

<cfloginuser name=”#cflogin.name#”

password=”#cflogin.password#” roles=”#session.user.roles#”>

<cfbreak>

</cfif>

</cfloop>

<cfif not loggedIn>

<cfset loginMessage = “Incorrect Login. Please try again”>

<cfinclude template=”loginForm.cfm”>

<cfabort>

</cfif>

<!--- display login form --->

<cfelse>

<cfinclude template=”loginForm.cfm”>

16513.7. Authentication Example

17 0672324628 CH13 6/8/05 11:09 AM Page 165

Page 189: ColdFusion MX Developer's Cookbook (Developer's Library)

166 Chapter 13 User Authentication and Authorization

<cfabort>

</cfif>

loginForm.cfm:<cfparam name=”loginMessage” type=”string” default=””>

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN”>

<html>

<head>

<title>ACME Intranet</title>

<style>

BODY { font-family:verdana,tahoma,sans-serif;font-size:10pt;}

TD { font-family:verdana,tahoma,sans-serif;font-size:10pt; }

.title { color:006699;font-weight:bold;font-size:16pt;}

.header { color:gray;font-weight:bold;font-size:11pt; }

.msg { color: red; font-weight: bold; font-size:8pt; }

.bottomLine { border-bottom : 1px solid gray; }

</style>

</head>

<body>

<div class=”title”>&nbsp;ACME Intranet</div>

<table border=”1” bordercolor=”white” cellpadding=”1”

cellspacing=”1” width=”100%”>

<tr height=”40”>

<td bgcolor=”C2CAC0” width=”4%”>&nbsp;</td>

<td bgcolor=”96B3B5” width=”16%”>&nbsp;</td>

<td bgcolor=”C1A99B” width=”25%”>&nbsp;</td>

<td bgcolor=”888483” width=”55%”>&nbsp;</td>

</tr>

<tr>

<td colspan=”4”>

<hr color=”silver” width=”100%” noshade size=”2” align=”center”>

<form method=”post”>

<table border=”0” width=”400” align=”center”>

<tr>

<td class=”bottomLine” colspan=”2”>

<span class=”header”>Please Login</span>

</td>

</tr>

<tr>

<td colspan=”2” align=”center”>

<span class=”msg”>

&nbsp;<cfoutput>#loginMessage#</cfoutput>

</span>

</td>

</tr>

<tr>

<td align=”right”>username:</td>

17 0672324628 CH13 6/8/05 11:09 AM Page 166

Page 190: ColdFusion MX Developer's Cookbook (Developer's Library)

16713.7. Authentication Example

<td>

<input type=”text” name=”j_username”

style=”border: 1px solid gray;”>

</td>

</tr>

<tr>

<td align=”right”>password:</td>

<td>

<input type=”password” name=”j_password”

style=”border: 1px solid gray;”>

</td>

</tr>

<tr><td class=”bottomLine” colspan=”2”>&nbsp;</td></tr>

<tr>

<td>&nbsp;</td>

<td align=”right”>

<input type=”submit” value=”login”

style=”border: 1px solid gray;background-color:white;”>

&nbsp;&nbsp;

</td>

</tr>

</table>

</form>

<hr color=”silver” width=”100%” noshade size=”2” align=”center”>

</td>

</tr>

</table>

</body>

</html>

user.cfc:<cfcomponent displayname=”User” hint=”Represents a logged in user”>

<cfset this.userID = -1>

<cfset this.displayName = “”>

<cfset this.firstName = “”>

<cfset this.city = “”>

<cfset this.state = “”>

<cfset this.country = “”>

<cfset this.email = “”>

<cfset this.phone = “”>

<cfset this.roles = “”>

</cfcomponent>

Authenticator.cfc:<cfcomponent displayname=”Authenticator”

hint=”defines base functionality for authentication”>

<cfset user = CreateObject(“component”, “User”)>

17 0672324628 CH13 6/8/05 11:09 AM Page 167

Page 191: ColdFusion MX Developer's Cookbook (Developer's Library)

168 Chapter 13 User Authentication and Authorization

<cffunction name=”authenticate” returntype=”boolean” output=”false”

hint=”returns true if credentials authenticate”>

<cfargument name=”username” type=”string” required=”true”>

<cfargument name=”password” type=”string” required=”true”>

<!--- you must extend AuthenticationMethod cfc --->

<cfthrow message=”authenticate must be defined in a sub class”>

</cffunction>

<cffunction name=”getUser” returntype=”User” output=”false”

hint=”returns the user that was authenticated”>

<cfreturn user>

</cffunction>

</cfcomponent>

SimpleAuthenticator.cfc:<cfcomponent extends=”Authenticator”

displayname=”SimpleAuthenticator” hint=”simple auth.”>

<cffunction name=”authenticate” returntype=”boolean” output=”false”>

<cfargument name=”username” type=”string” required=”true”>

<cfargument name=”password” type=”string” required=”true”>

<!--- simply check to see if they are the same --->

<cfif arguments.password IS arguments.username>

<cfset user.userID = arguments.username>

<cfset user.displayName = arguments.username>

<cfset user.roles = “users”>

<cfreturn true>

<cfelse>

<!--- pass not = to user, not authenticated --->

<cfreturn false>

</cfif>

</cffunction>

</cfcomponent>

DatabaseAuthenticator.cfc:<cfcomponent extends=”Authenticator”

displayname=”DatabaseAuthentication” hint=”uses database”>

<cffunction name=”authenticate” returntype=”boolean” output=”false”>

<cfargument name=”username” type=”string” required=”true”>

<cfargument name=”password” type=”string” required=”true”>

<!--- is it a valid user? --->

<cfquery datasource=”#request.dsn#” name=”userInfo”>

SELECT UserID, FirstName, LastName, City, State,

17 0672324628 CH13 6/8/05 11:09 AM Page 168

Page 192: ColdFusion MX Developer's Cookbook (Developer's Library)

16913.7. Authentication Example

Country, Email, Phone

FROM users

WHERE UserName = ‘#arguments.username#’

AND PassWord = ‘#arguments.password#’

</cfquery>

<cfif userInfo.recordcount>

<!--- get roles for user --->

<cfquery datasource=”#request.dsn#” name=”userroles”>

SELECT r.name

FROM roles AS r, user_roles AS ur

WHERE ur.UserID = #userInfo.UserID#

AND ur.RoleID = r.RoleID

</cfquery>

<!--- convert query column to list --->

<cfset roles = ValueList(userroles.name)>

<!--- populate the user cfc object --->

<cfset user.displayName = userInfo.FirstName>

<cfset user.firstName = userInfo.FirstName>

<cfset user.lastName = userInfo.LastName>

<cfset user.city = userInfo.City>

<cfset user.state = userInfo.State>

<cfset user.country = userInfo.Country>

<cfset user.email = userInfo.Email>

<cfset user.phone = userInfo.Phone>

<cfset user.roles = roles>

<cfset user.userID = userInfo.UserID>

<cfreturn true>

<!--- bad username or password --->

<cfelse>

<!--- try login again --->

<cfreturn false>

</cfif>

</cffunction>

</cfcomponent>

LDAPAuthenticator.cfc:<cfcomponent extends=”Authenticator”

displayname=”LDAPAuthenticator” hint=”LDAP auth.”>

<!--- your Active Directory Domain --->

<cfset domain = “mycompany.com”>

<!--- the address of your ldap server --->

<cfset ldapServer = “localhost”>

<!--- the base DN to use when querying the server --->

17 0672324628 CH13 6/8/05 11:09 AM Page 169

Page 193: ColdFusion MX Developer's Cookbook (Developer's Library)

170 Chapter 13 User Authentication and Authorization

<cfset ldapBaseDn = “dc=mycompany,dc=com”>

<!--- the user ldap attribute for comparing against the username --->

<cfset ldapUidAttr = “sAMAccountName”>

<!--- the user ldap attribute for finding a user’s groups or roles --->

<cfset ldapRoleAttr = “memberOf”>

<!--- the group ldap attribute for getting a role’s name --->

<cfset ldapRoleNameAttr = “name”>

<!--- map ldap user attribute names to expected session variable names --->

<cfset ldapmap = StructNew()>

<cfset ldapmap.displayName = “displayName”>

<cfset ldapmap.firstName = “givenName”>

<cfset ldapmap.lastName = “sn”>

<cfset ldapmap.city = “l”>

<cfset ldapmap.state = “st”>

<cfset ldapmap.country = “c”>

<cfset ldapmap.email = “mail”>

<cfset ldapmap.phone = “telephonenumber”>

<cffunction name=”authenticate” returntype=”boolean” output=”false”>

<cfargument name=”username” type=”string” required=”true”>

<cfargument name=”password” type=”string” required=”true”>

<cftry>

<cfset filter=”(#ldapUidAttr#=#username#)”>

<cfset attributes=””>

<cfloop list=”#StructKeyList(ldapmap)#” index=”prop”>

<cfset ldapattr = StructFind(ldapmap,prop)>

<cfset attributes = ListAppend(attributes,ldapattr)>

</cfloop>

<!--- attempt to authenticate the user and

download his/her profile info --->

<cfldap server=”#ldapServer#”

username=”#arguments.username#@#domain#”

password=”#arguments.password#”

action=”query”

start=”#ldapBaseDn#”

filter=”#filter#”

attributes=”#attributes#”

name=”results”>

<!--- set the user properties --->

<cfloop list=”#StructKeyList(ldapmap)#” index=”prop”>

<cfset ldapattr = StructFind(ldapmap,prop)>

<cfset ldapval = StructFind(results,ldapattr)>

<cfset tmp = SetVariable(“user.#prop#”,ldapval)>

</cfloop>

17 0672324628 CH13 6/8/05 11:09 AM Page 170

Page 194: ColdFusion MX Developer's Cookbook (Developer's Library)

17113.7. Authentication Example

<!--- get the user’s roles --->

<cfldap server=”#ldapServer#”

username=”#arguments.username#@#domain#”

password=”#arguments.password#”

action=”query”

start=”#ldapBaseDn#”

filter=”#filter#”

attributes=”#ldapRoleAttr#”

name=”groups”>

<cfset roles = ArrayNew(1)>

<cfset i = 1>

<cfset grouplist = StructFind(groups,ldapRoleAttr)>

<cfset grouplist = Replace(grouplist,”, “,chr(253),”all”)>

<cfloop list=”#grouplist#” index=”group” delimiters=”#chr(253)#”>

<!--- get the role detail --->

<cfldap server=”#ldapServer#”

username=”#arguments.username#@#domain#”

password=”#arguments.password#”

action=”query”

start=”#group#”

filter=”(objectClass=*)”

attributes=”#ldapRoleNameAttr#”

name=”thisGroup”>

<cfset roleName = StructFind(thisGroup,ldapRoleNameAttr)>

<cfset roles[i] = roleName>

<cfset i = i + 1>

</cfloop>

<cfset rolelist = ArrayToList(roles)>

<cfset user.userID = arguments.username>

<cfset user.roles = rolelist>

<cfreturn true>

<cfcatch type=”any”>

<cfreturn false>

</cfcatch>

</cftry>

</cffunction>

<cffunction name=”setDomain” output=”false” returntype=”void”>

<cfargument name=”domain” type=”string” required=”true”>

<cfset domain = arguments.domain>

</cffunction>

<cffunction name=”setServer” output=”false” returntype=”void”>

<cfargument name=”server” type=”string” required=”true”>

17 0672324628 CH13 6/8/05 11:09 AM Page 171

Page 195: ColdFusion MX Developer's Cookbook (Developer's Library)

172 Chapter 13 User Authentication and Authorization

<cfset ldapServer = arguments.server>

</cffunction>

<cffunction name=”setBaseDN” output=”false” returntype=”void”>

<cfargument name=”baseDN” type=”string” required=”true”>

<cfset ldapBaseDN = arguments.basedN>

</cffunction>

</cfcomponent>

acmeIntranet.cfm:<!--- make sure session variables don’t expire --->

<cfif NOT IsDefined(“session.user”)>

<cflogout>

<cflocation url=”loginForm.cfm”>

</cfif>

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN”>

<html>

<head>

<title>ACME Intranet</title>

<style>

BODY { font-family:verdana,tahoma,sans-serif;font-size:10pt;}

TD { font-family:verdana,tahoma,sans-serif;font-size:10pt; }

.title { color:006699;font-weight:bold;font-size:16pt;}

.header { color:gray;font-weight:bold;font-size:11pt; }

.bottomLine { border-bottom : 1px solid gray; }

A { color:006699;}

</style>

</head>

<body>

<div class=”title”>&nbsp;ACME Intranet</div>

<table border=”1” bordercolor=”white”

cellpadding=”1” cellspacing=”0” width=”100%”>

<tr height=”40”>

<td bgcolor=”C2CAC0” width=”4%”>&nbsp;</td>

<td bgcolor=”96B3B5” width=”16%”>&nbsp;</td>

<td bgcolor=”C1A99B” width=”25%”>&nbsp;</td>

<td bgcolor=”888483” width=”55%”>&nbsp;</td>

</tr>

<tr>

<td colspan=”4”>

<hr color=”silver” width=”100%” noshade size=”2” align=”center”>

<div class=”header”>

Welcome <cfoutput>#session.user.displayName#</cfoutput>,

17 0672324628 CH13 6/8/05 11:09 AM Page 172

Page 196: ColdFusion MX Developer's Cookbook (Developer's Library)

17313.7. Authentication Example

</div>

<p>

Below you will find operations that you can

perform in the intranet.

</p>

<cfif IsUserInRole(“users”)>

<table border=”0” cellpadding=”2” cellspacing=”0” width=”80%”>

<tr>

<td class=”bottomLine”>

<span class=”header”>User Options</span>

</td>

</tr>

<tr>

<td>

<ul type=”square” style=”color:gray”>

<li>

<a href=”editUser.cfm”>Edit User Settings</a> -

change your password, or contact info

</li>

<li>

<a href=”addDoc.cfm”>Add a Document</a> -

add a document to the intranet

</li>

<li>

<a href=”viewDoc.cfm”>View Documents</a> -

view documents in the intranet

</li>

<li>

<a href=”email.cfm”>Check Email</a> -

check your email

</li>

</ul>

</td>

</tr>

</table>

</cfif>

<cfif IsUserInRole(“administrators”)>

<table border=”0” cellpadding=”2” cellspacing=”0” width=”80%”>

<tr>

<td class=”bottomLine”>

<span class=”header”>Administrator Options</span>

</td>

</tr>

<tr>

<td>

17 0672324628 CH13 6/8/05 11:09 AM Page 173

Page 197: ColdFusion MX Developer's Cookbook (Developer's Library)

174 Chapter 13 User Authentication and Authorization

<ul type=”square” style=”color:gray”>

<li>

<a href=”editUsers.cfm”>Edit User Settings</a> -

change password, or contact info for other users

</li>

<li>

<a href=”addUser.cfm”>Add a User</a> -

add a new user to the intranet

</li>

<li>

<a href=”deleteUser.cfm”>Delete User</a> -

view documents in the intranet

</li>

</ul>

</td>

</tr>

</table>

</cfif>

<div align=”right”><A href=”logout.cfm”>Log Out</A></div>

<hr color=”silver” width=”100%” noshade size=”2” align=”center”>

</td>

</tr>

</table>

</body>

</html>

CommentsThus far, you have not seen any authentication code that can work with more than oneuser.This section shows you how to build an application that not only authenticatesmore than one user, but can also authenticate from several repositories (database, LDAP,and simple).

The application.cfm file is easy to read because all the authentication logic hasbeen moved into loginLogic.cfm and a <cfinclude> is used to include it.

The loginLogic.cfm page includes loginForm.cfm if a username and passwordare not sent in the page request, or if authentication fails.The login form will promptthe user for a username and password, and display an error message if applicable (seeFigure 13.1). If the username and password are supplied, loginLogic.cfm attempts toauthenticate the credentials against each authenticator component.The authType vari-able in application.cfm defines a list of names for each authenticator used by theapplication. In loginLogic.cfm, instances of each authenticator are created dynamical-ly by looping through the authType list.

17 0672324628 CH13 6/8/05 11:09 AM Page 174

Page 198: ColdFusion MX Developer's Cookbook (Developer's Library)

17513.7. Authentication Example

Figure 13.1 The output of loginForm.cfm, where the user logs in to the application.

The main design goal of this example is to be able to easily plug-and-play differentauthentication methods. CFCs (covered in Chapter 19) are a great way to accomplishthis goal.The first CFC in this example is a CFC called User, which is used to holdinformation about a user when logged in. By using the this keyword, the CFC vari-ables are publicly accessible, and can be accessed with dot notation(cfcInstance.variableName).

The next CFC is called Authenticator; it defines a framework for the authentica-tion methods (database, LDAP, and simple) to inherit from. Each authentication methodwill define a CFC that inherits from the Authenticator CFC, and overrides the pseu-do-abstract method “authenticate”.The Authenticator CFC holds an instance of aUser CFC, which is accessible through the getUser function. CFCs that inherit fromAuthenticator populate the User object with information when the authenticatemethod is called.

The simple authenticator CFC simply determines whether the username and pass-word are the same. If they match, the user will be logged in.You may notice that theexample doesn’t populate all of the fields in the user object because it doesn’t have allthe information.This is one advantage to using a CFC to store the user information overa structure—you can define default values.

Next take a take a look at the database authenticator.The example uses a databasewith the following structure, listed in Tables 13.1-13.3.

17 0672324628 CH13 6/8/05 11:09 AM Page 175

Page 199: ColdFusion MX Developer's Cookbook (Developer's Library)

176 Chapter 13 User Authentication and Authorization

Table 13.1 The user Table

Column Name Data Type

UserID Auto incrementing integer (identity field), primary key

UserName Text/varchar

PassWord Text/varchar

FirstName Text/varchar

LastName Text/varchar

City Text/varchar

State Text/varchar

Country Text/varchar

Email Text/varcharPhone Text/varchar

Table 13.2 The role Table

Column Name Data Type

RoleID Auto incrementing integer (identity field), primary keyName Text/varchar

Table 13.3 The user_roles Table

Column Name Data Type

UserID IntegerRoleID Integer

The database design allows you to easily modify both the users and the roles independ-ently.The design also allows users and roles to have a many-to-many relationship, mean-ing each user can have multiple roles, and each role can be assigned to multiple users.

The final authenticator, the LDAP authenticator, is perhaps the most powerful yet,because it allows you to connect to enterprise directory servers such as Microsoft ActiveDirectory. By changing some of the default values, or by calling the setDomain,setServer, and setBaseDN functions, you should be able to connect to any Windows2000 Active Directory and authenticate users against it.The <cfldap> tag is covered indetail in Chapter 11,“Using Internet Protocols.”

The main page of the Acme Intranet example (acmeIntranet.cfm) uses theIsUserInRole function to determine which links to show the user, as shown in Figure13.2.The administrators have more options than regular users. Each page in your appli-cation that is restricted to specific roles should call the IsUserInRole function beforedisplaying the page.

17 0672324628 CH13 6/8/05 11:09 AM Page 176

Page 200: ColdFusion MX Developer's Cookbook (Developer's Library)

17713.7. Authentication Example

Figure 13.2 The main page, acmeIntranet.cfm, shows the appropriate content based on the user’s access level.

Notice that, at the top of the page, the program determines whether the session variablesare defined.As mentioned, <cflogin> doesn’t exactly use session variables to maintainstate, and because of this, it is possible for session variables to expire before the <cflogin> variables do.

17 0672324628 CH13 6/8/05 11:09 AM Page 177

Page 201: ColdFusion MX Developer's Cookbook (Developer's Library)

17 0672324628 CH13 6/8/05 11:09 AM Page 178

Page 202: ColdFusion MX Developer's Cookbook (Developer's Library)

IVDatabase Integration

14 Structured Query Language (SQL)

15 Stored Procedures

18 0672324628 Part 04 6/8/05 11:09 AM Page 179

Page 203: ColdFusion MX Developer's Cookbook (Developer's Library)

18 0672324628 Part 04 6/8/05 11:09 AM Page 180

Page 204: ColdFusion MX Developer's Cookbook (Developer's Library)

14Structured Query Language (SQL)

14.0. IntroductionWhen ColdFusion 1.0 was released there were no .CFM files, no <cfset> tag, not even<cfif>. ColdFusion did however have .DBM files and a <dbif> tag.The DB stood fordatabase; ColdFusion was born to connect the database and the Web browser.ColdFusion can do much more today than it could in its inception; however, its primarypurpose is still to connect databases with the Web.

Although databases are often integral parts of ColdFusion applications, database designand query performance are often overlooked in the development process. ImprovingSQL queries and utilizing the facilities of the database server can solve many perform-ance problems.

Structured Query Language (SQL) is the common language that all relational data-bases speak, with a few different dialects. Most of the time, your SQL statement will runwithout modification on several database servers.

SQL has several underused capabilities that I hope you will unleash after reading thischapter.

This chapter uses the same database tables to present all of the examples. Table 14.1stores all of the employees and information related strictly to each employee.

Table 14.1 employees Table

Column Name Data Type

EmployeeID Auto Incrementing integer (identity field), primary key

Name Text/varchar

Age Number/integer

Salary Currency/money

19 0672324628 CH14 6/8/05 11:09 AM Page 181

Page 205: ColdFusion MX Developer's Cookbook (Developer's Library)

182 Chapter 14 Structured Query Language (SQL)

Resume TextDepartmentID Integer (foreign key)

Table 14.2 stores the departments. Each employee must belong to exactly one depart-ment, and each department can have several employees.The relationship between depart-ments and employees is called a one-to-many relationship, sometimes noted as 1-N.

Table 14.2 department Table

Column Name Data Type

DepartmentID Auto Incrementing integer (identity field), primary keyName Text/Varchar

Next, you need to store information about the projects; the structure for the projectstable is listed in Table 14.3.

Table 14.3 projects Table

Column Name Data Type

ProjectID Auto Incrementing integer (identity field), primary keyName Text/Varchar

Each employee can work on more than one project and each project can have morethan one employee assigned to it.This is known as a many-to-many relationship or a N-N relationship, and is represented in Table 14.4.

Table 14.4 The employee_projects Table Is a Many-to-Many Relationship

Column Name Data Type

EmployeeID IntegerProjectID Integer

The employee_projects table uses two foreign keys to link the employees and proj-ects table together.The two foreign keys together become the primary key for theemployee_projects table.

It would be a good idea to populate your database in order to run the examples inthe following sections. Most databases provide a user interface that allows you to adddata to a table.

Table 14.1 Continued

Column Name Data Type

19 0672324628 CH14 6/8/05 11:09 AM Page 182

Page 206: ColdFusion MX Developer's Cookbook (Developer's Library)

18314.2. Updating Data

14.1. Inserting DataYou want to add a new row to a table.

TechniqueUse the INSERT INTO and VALUES keywords to insert a new row in to a table.

<cfquery datasource=”cfcookbook”>

INSERT INTO employees (Name, Age, Salary, DepartmentID)

VALUES(‘Bob’, 31, 50000, 1)

</cfquery>

CommentsInserting data into a database is fairly easy compared to selecting data, which is why it’scovered first.The INSERT keyword is used to tell the database that you want to add datato it.You use the INTO keyword to tell the database which table you are inserting into.After the table name, a list of columns is specified, and finally a list of values.

You may notice that you don’t need to specify every column defined in the table toinsert. EmployeeID isn’t included because it is defined in the database as an auto-numbering identity, which means the database will populate that field automaticallywhen you perform the insert.The Resume field is not included in this INSERT state-ment either; you may leave fields out of the INSERT statement if they are defined in thedatabase to allow NULL values, or don’t require a value.You can also set up your databaseto populate fields with default values.

Although it’s not very common anymore, from time to time developers may omit thelist of column names from the table in their insert statement.This will not cause anerror on most databases, but it will eventually make someone’s life difficult, and possiblyyour own.When the column list is not present, the database will use the order in whichthe fields were created to determine where to place which value.This is something toavoid if you’re at all concerned with writing maintainable code.

INSERT INTO employees

VALUES(‘Bob’, 31, 50000, 1)

14.2. Updating DataYou want to update one or more columns in an existing row.

TechniqueUse the UPDATE and SET keywords to change data in your database.

19 0672324628 CH14 6/8/05 11:09 AM Page 183

Page 207: ColdFusion MX Developer's Cookbook (Developer's Library)

184 Chapter 14 Structured Query Language (SQL)

<cfquery datasource=”cfcookbook”>

UPDATE employees

SET Salary = 1000000,

Name = ‘Rich’

WHERE EmployeeID = 1

</cfquery>

CommentsTo change the data in your tables, the UPDATE keyword is used.After the UPDATE key-word, the table name is specified, and then the SET statement tells the database whichvalues to update. Several fields can be updated at once by separating them with commasin the SET clause.

Rows are typically updated one at a time, and a good way to do this is by testing theprimary key in the WHERE clause. If you omit the WHERE clause, all the rows in the tablewill be updated.The WHERE clause is discussed in detail later in this chapter.

14.3. Deleting DataYou want to delete a row from a table.

TechniqueUse the DELETE keyword to delete rows from your table.

<cfquery datasource=”cfcookbook”>

DELETE FROM employees

WHERE EmployeeID = 1

</cfquery>

CommentsWhen you delete data from a database with SQL, you should use a WHERE clause tolimit which rows will be deleted (just as you do with the UPDATE statement). If youdon’t include a WHERE clause, every row in your table will be deleted.

Microsoft Access requires that you specify columns to delete from after the DELETEkeyword.

DELETE * FROM employees

WHERE EmployeeID = 1

19 0672324628 CH14 6/8/05 11:09 AM Page 184

Page 208: ColdFusion MX Developer's Cookbook (Developer's Library)

18514.5. Limiting Rows Returned

14.4. Selecting DataYou want to select some data from a database.

TechniqueUse the SELECT statement to retrieve information from the database.

<cfquery datasource=”cfcookbook” name=”employeeNames”>

SELECT Name FROM employees

</cfquery>

<cfdump var=”#employeeNames#”>

CommentsThe trick to mastering SQL is mastering the SELECT statement. Retrieving informationfrom the database that you need is typically much more difficult than manipulating oradding data.

The query shown here can be used to select the names of all employees from thedatabase.The SELECT keyword tells the database which action you are performing.Afterthe SELECT keyword, you specify a list of columns. In this example, you just want theemployee’s name, so you simply write Name.The FROM keyword tells the database fromwhich table(s) to return data.

Many novice SQL developers might write the SQL in this technique the following way:

SELECT * FROM employeesThis code still works, but it returns the EmployeeID, Age, Salary, Resume, andDepartmentID along with the employee names. SELECT * means to return allcolumns in the table; this often means that you are asking the database to do more thanit needs to. Never select more information than you need. Not only can this shortcut getyou into trouble with the performance police (they’re out there, watch out!), but it alsomakes it difficult to maintain the code.

The <cfdump> tag is used to display the results of any variable (passed in through thevar attribute) neatly in a table. It’s used here, and throughout the chapter, to display theresults of the query.

14.5. Limiting Rows ReturnedYou want to return rows that meet a certain condition.

TechniqueUse the WHERE keyword to limit the rows returned.

<cfquery datasource=”cfcookbook” name=”petes”>

SELECT Name FROM employees

19 0672324628 CH14 6/8/05 11:09 AM Page 185

Page 209: ColdFusion MX Developer's Cookbook (Developer's Library)

WHERE Name = ‘Pete’

</cfquery>

<cfdump var=”#petes#”>

CommentsBecause you usually don’t need to return all the rows in a table, SQL offers the WHEREclause.The WHERE clause allows you to limit the results returned.This example returnsall employees named Pete. Notice that you must place single quotes around ‘Pete’ toindicate that it is a string.This is required for strings. On numeric fields, the singlequotes are not allowed.This requirement is a common source of error.

Several operators are available for use within a WHERE clause; some of the commonones are outlined in Table 14.5.

Table 14.5 Common SQL Operators

Operator Meaning

= Equal to

<> Not equal to

> Greater than

< Less than

>= Greater than or equal to

<= Less than or equal to

IN In a list of values (see Section 14.6)

LIKE Matches a pattern (see Section 14.7)

AND Logical ANDOR Logical OR

14.6. Specifying Multiple ConditionsYou want to return rows that meet multiple conditions.

TechniqueUse the AND or OR operators to specify multiple conditions in the WHERE clause.

<cfquery datasource=”cfcookbook” name=”richKids”>

SELECT Name FROM employees

WHERE Salary > 100000

AND Age < 30

</cfquery>

<cfdump var=”#richKids#”>

186 Chapter 14 Structured Query Language (SQL)

19 0672324628 CH14 6/8/05 11:09 AM Page 186

Page 210: ColdFusion MX Developer's Cookbook (Developer's Library)

18714.8. Using Aliases

CommentsThe SQL in this technique selects all employees that have salaries larger than $100,000and are younger than 30 years of age.The AND operator is used to indicate that bothconditions must be true.The OR operator is used syntactically exactly the same way asthe AND operator but it holds a different meaning.

You can use parentheses to group together OR and AND statements, much like you canwith <cfif>.

14.7. Sorting ResultsYou want your result set to be sorted by one or more columns.

TechniqueUse the ORDER BY keywords to sort the result of a query by a specific column orcolumns.

<cfquery datasource=”cfcookbook” name=”sortedEmployees”>

SELECT Name, Age FROM employees

ORDER BY Name DESC, Age

</cfquery>

<cfdump var=”#sortedEmployees#”>

CommentsThe ORDER BY keywords are followed by a list of columns that have been selected inthe SELECT statement.The results are sorted in ascending order by default.You can alsochange the order by using the DESC (descending order) keyword or the ASC (ascendingorder) keyword.This SQL statement returns all names and ages first sorted by name (Z-A descending order). If any rows have the same name, they are sorted by age.

14.8. Using AliasesYou want to refer to columns or tables as different names.

TechniqueUse the AS keyword to create an alias.

<cfquery datasource=”cfcookbook” name=”alias”>

SELECT e.Name AS EmployeeName

FROM employees AS e

</cfquery>

19 0672324628 CH14 6/8/05 11:09 AM Page 187

Page 211: ColdFusion MX Developer's Cookbook (Developer's Library)

<cfoutput query=”alias”>

#alias.EmployeeName# <br>

</cfoutput>

CommentsThe AS keyword can be used to create an alias to a column name in the result set, or tocreate an alias to a table name used within the SQL statement.The syntax for the key-word is the same in both cases; after the real name for the object, you add ASAliasName.

Using column name aliases is useful in aggregate functions (covered in Section14.12).Table name aliases are useful when joining tables, which is covered next.

14.9. Selecting from Multiple TablesYou want to pull data from more than one table.

TechniqueSpecify multiple tables in the FROM statement to select data from multiple tables.

<cfquery datasource=”cfcookbook” name=”empDepartments”>

SELECT e.EmployeeID, e.Name, e.DepartmentID, d.DepartmentID, d.Name

FROM employees AS e, departments AS d

</cfquery>

<cfdump var=”#empDepartments#”>

CommentsA join allows you to retrieve related information from multiple tables in a single query.The output of the code in this technique, which includes two employees and twodepartments in the database, is shown in Table 14.6.

Table 14.6 Result of This Technique

EmployeeID Name DepartmentID DepartmentID Name

1 Emp1 1 1 Dept1

1 Emp1 1 2 Dept2

2 Emp2 2 1 Dept1

2 Emp2 2 2 Dept2

The database returns the cross product (or Cartesian product) of employees and depart-ments.This is known as a cross join, and is essential to understanding inner and outer

188 Chapter 14 Structured Query Language (SQL)

19 0672324628 CH14 6/8/05 11:09 AM Page 188

Page 212: ColdFusion MX Developer's Cookbook (Developer's Library)

18914.11. Joining Three Tables

joins.The total number of records returned (the recordcount) in a cross join is always thenumber of rows in the first table multiplied by the number of rows in the second.This means that if either your employees table or your departments table have zerorecords, the query would not return any rows, because zero multiplied by anything iszero.That rule is important to keep in mind when you are performing inner joins, andmotivates the need for outer joins.

14.10. Joining Two TablesYou want to select related data from two tables.

TechniqueUse a WHERE statement that requires that the primary key in one table match a foreignkey in the other table.

<cfquery datasource=”cfcookbook” name=”joinEmpDept”>

SELECT e.Name AS EmpName, d.Name AS DeptName

FROM employees AS e, departments AS d

WHERE e.DepartmentID = d.DepartmentID

</cfquery>

<cfdump var=”#joinEmpDept#”>

CommentsThe SQL in this technique is very similar to the previous technique except that it adds aWHERE statement.The WHERE statement limits the result of the cross product to the rowsin which the DepartmentIDs from the employees and departments tables match.You cansee in Table 14.6 that the DepartmentIDs from the employees table and department tablematch in the first and last row. Only the two matching rows are returned in this query,instead of a complete cross product.

In this query, the employee’s DepartmentID is the foreign key and the department’sDepartmentID is the primary key.The resulting query shows each employee along withthe department they belong to.

14.11. Joining Three TablesYou want to select related data from three tables.

TechniqueUse a WHERE statement with two conditions that match the primary keys with the for-eign keys.

19 0672324628 CH14 6/8/05 11:09 AM Page 189

Page 213: ColdFusion MX Developer's Cookbook (Developer's Library)

190 Chapter 14 Structured Query Language (SQL)

<cfquery datasource=”cfcookbook” name=”empProjects”>

SELECT e.Name AS EmpName, p.Name AS ProjName

FROM employees AS e, projects AS p, employee_projects AS ep

WHERE e.EmployeeID = ep.EmployeeID

AND ep.ProjectID = p.ProjectID

ORDER BY e.Name

</cfquery>

<cfdump var=”#empProjects#”>

CommentsThe result of this technique is a complete list of all employees assigned to projects.Notice that it includes two join conditions because you are selecting from three tables.Here the employee_projects table holds foreign keys to the employees and projects tables.

14.12. Grouping Data with CFOUTPUTYou want to display data in groups.

TechniqueUse the group attribute of the <cfoutput> tag to output data in groups.

<cfquery datasource=”cfcookbook” name=”empProjects”>

SELECT e.Name AS EmpName, p.Name AS ProjName

FROM employees AS e, projects AS p, employee_projects AS ep

WHERE e.EmployeeID = ep.EmployeeID

AND ep.ProjectID = p.ProjectID

ORDER BY e.Name

</cfquery>

<cfoutput query=”empProjects” group=”EmpName”>

#empProjects.EmpName#<br>

<ul>

<cfoutput>

<li>#empProjects.ProjName#</li>

</cfoutput>

</ul>

</cfoutput>

19 0672324628 CH14 6/8/05 11:09 AM Page 190

Page 214: ColdFusion MX Developer's Cookbook (Developer's Library)

19114.13. Performing Outer Joins

CommentsThe <cfoutput> tag provides a useful attribute, called group, that allows you to take aquery like the one described in the previous section and group the data by a column inthat query. For instance, you can group by the EmpName column to display each employ-ee and the projects they are assigned to.The nested <cfoutput> tag is used to iterateover each project, and the outer <cfoutput> tag is used to iterate over each employee.

14.13. Performing Outer JoinsYou want to perform a join that returns all rows even if the keys do notmatch.

TechniqueUse the LEFT OUTER JOIN keyword to join all rows in a table.

<cfquery datasource=”cfcookbook” name=”allEmpProjects”>

SELECT e.Name AS EmpName, ProjectID

FROM employees AS e LEFT OUTER JOIN

employee_projects AS ep ON e.EmployeeID = ep.EmployeeID

</cfquery>

<cfdump var=”#allEmpProjects#”>

CommentsThe joins you have seen thus far are known as inner joins, or cross joins. In many data-base implementations, there exists another type of join, known as an outer join.There arethree types of outer joins: left outer join, right outer join, and full outer join.

This query returns all employees in the table and their project IDs, whereby an innerjoin would have returned only the employees that had project IDs (employees who wereassigned to a project).The query returns NULL in the ProjectID field for thoseemployees who don’t have a Project ID.

If you were to change the LEFT OUTER JOIN in the query to a RIGHT OUTERJOIN, the query would return all the projects, even the ones that didn’t have anyemployees assigned to them.This is known as a right outer join.The EmpName fieldwould be NULL for those projects that do not have an employee.

A FULL OUTER JOIN would return employees who aren’t assigned to any projects,as well as projects that aren’t assigned to any employees. Here, either the ProjectIDfield or the EmpName field can be NULL, but never both in the same row.The code inthis technique can be changed to a full join by replacing LEFT OUTER JOIN withFULL OUTER JOIN.

19 0672324628 CH14 6/8/05 11:09 AM Page 191

Page 215: ColdFusion MX Developer's Cookbook (Developer's Library)

192 Chapter 14 Structured Query Language (SQL)

14.14. Selecting Unique ValuesYou want to select only distinct values for a particular column.

TechniqueUse the DISTINCT keyword to select only unique values from a table.

<cfquery datasource=”cfcookbook” name=”distinctSalaries”>

SELECT DISTINCT Salary

FROM employees

</cfquery>

<cfdump var=”#distinctSalaries#”>

CommentsThe DISTINCT operator ensures that there are no duplicate values for a specific columnin a result set.This query displays a list of all the different salaries that employees current-ly have.

14.15. Using Aggregate FunctionsYou want to perform an operation (such as an average or sum) against multiplerows in the database.

TechniqueUse an aggregate function such as AVG() to perform the operation on all the rows inthe table.

<cfquery datasource=”cfcookbook” name=”avgSalary”>

SELECT AVG(Salary) AS AvgSalary

FROM employees

</cfquery>

<cfoutput>

The average salary is #DollarFormat(avgSalary.AvgSalary)#

</cfoutput>

CommentsAggregate functions allow you to perform operations (such as averages) on all of the val-ues in a particular column.This query shows you the average salary in the organization.

19 0672324628 CH14 6/8/05 11:09 AM Page 192

Page 216: ColdFusion MX Developer's Cookbook (Developer's Library)

19314.16. Grouping Aggregate Data

The result of this query is one row with one column (called AvgSalary).A query thatcontains aggregate functions can contain multiple aggregate functions, but cannot selectnon-aggregate data (for example, average salary and maximum salary may be selectedtogether, but you cannot add Name to the SELECT statement). In order to use non-aggregate functions, you have to use a GROUP BY clause, covered in the next section.Table 14.7 lists some common aggregate functions.

Table 14.7 Common SQL Aggregate Functions

Function Meaning

AVG(column) Average of all values in column

MAX(column) Maximum value in column

MIN(column) Minimum value in column

SUM(column) The sum of all values in columnCOUNT(column) The number of values in the column

These aggregate functions can only be used with numeric columns, except for theCOUNT() function, which can be used on any type of column.

14.16. Grouping Aggregate DataYou want to group together related data.

TechniqueUse a GROUP BY clause to specify which columns to group by.

<cfquery datasource=”cfcookbook” name=”avgDeptSalaryAge”>

SELECT d.Name, AVG(Salary) AS AvgSalary, AVG(Age) AS AvgAge

FROM employees AS e, departments AS d

WHERE e.DepartmentID = d.DepartmentID

GROUP BY d.Name

</cfquery>

<cfdump var=”#avgDeptSalaryAge#”>

CommentsWith a GROUP BY clause, you can force aggregate functions to work only on groups ofdata.This query shows the average salary and average age in each department.

19 0672324628 CH14 6/8/05 11:09 AM Page 193

Page 217: ColdFusion MX Developer's Cookbook (Developer's Library)

194 Chapter 14 Structured Query Language (SQL)

14.17. Limiting Aggregate ResultsYou want to place a condition on aggregate functions.

TechniqueUse a HAVING clause to limit the results of an aggregate function.

<cfquery datasource=”cfcookbook” name=”deptOverThirty”>

SELECT d.Name AS department

FROM employees AS e, departments AS d

WHERE e.DepartmentID = d.DepartmentID

GROUP BY d.Name

HAVING AVG(e.Age) > 30

</cfquery>

<cfdump var=”#deptOverThirty#”>

CommentsThe HAVING clause is used to place a condition on aggregate functions.You can use thequery shown here to determine which departments have an average age above 30.

The GROUP BY clause is required when you use a HAVING clause with non-aggregatefunction arguments in the SELECT clause.

14.18. Using the IN KeywordYou want to select records with field values found in a predetermined list ofvalues.

TechniqueUse the IN keyword to select within a list of values.

<cfquery datasource=”cfcookbook” name=”empAge”>

SELECT Name

FROM employees

WHERE Age IN (30, 40, 50)

</cfquery>

<cfdump var=”#empAge#”>

19 0672324628 CH14 6/8/05 11:09 AM Page 194

Page 218: ColdFusion MX Developer's Cookbook (Developer's Library)

19514.19. Using IN with Web Forms

CommentsThe IN keyword is a useful shortcut when you have a list of possible values for a column.

This query returns the names of employees with ages 30, 40, or 50. IN does notintroduce any new functionality.The same query can also be written with the OR and =operator (as shown next).

SELECT Name

FROM employees

WHERE Age = 30

OR Age = 40

OR Age = 50

However, it is much easier to use IN, especially when you have a list of values.

14.19. Using IN with Web FormsYou want to select data based on which check boxes are enabled.

TechniqueUse the list generated from a check box in the IN statement.

<cfquery datasource=”cfcookbook” name=”depts”>

SELECT DISTINCT DepartmentID, Name

FROM departments

</cfquery>

<form method=”post”>

<cfoutput query=”depts”>

<input type=”Checkbox” name=”DepartmentList”

value=”#depts.DepartmentID#”> #depts.Name#<br>

</cfoutput>

<input type=”submit” value=”Get Employees”>

</form>

<cfif IsDefined(“form.DepartmentList”)>

<cfquery datasource=”cfcookbook” name=”employees”>

SELECT e.Name AS EmpName, e.Age, e.Salary, d.Name AS DeptName

FROM employees AS e, departments AS d

WHERE e.DepartmentID IN (#form.DepartmentList#)

AND e.DepartmentID = d.DepartmentID

ORDER BY DeptName

</cfquery>

<cfif employees.recordcount>

19 0672324628 CH14 6/8/05 11:09 AM Page 195

Page 219: ColdFusion MX Developer's Cookbook (Developer's Library)

196 Chapter 14 Structured Query Language (SQL)

<cfoutput query=”employees” group=”DeptName”>

<b>Employees in #DeptName#</b><br>

<table border=”1”>

<tr>

<td><b>Name</b></td>

<td><b>Age</b></td>

<td><b>Salary</b></td>

</tr>

<cfoutput>

<tr>

<td>#EmpName#</td>

<td>#Age#</td>

<td>#Salary#</td>

</tr>

</cfoutput>

</table>

</cfoutput>

<cfelse>

Sorry No Employees.

</cfif>

</cfif>

CommentsThe IN keyword comes in handy when you are working with HTML forms, specificallywith check boxes and multiple select lists.The users selection gets translated into acomma-separated list in ColdFusion; exactly what the IN keyword takes as an argument.This example page allows users to check multiple departments and view all employees ineach department.

IN statements can also be used with text values; however, each value needs to havesingle quotes wrapping them.You can use ColdFusion’s ListQualify function to addsingle quotes to the list. Lists are discussed in depth in Chapter 2,“Working with Lists,”and ListQualify is discussed in Section 2.8,“Adding Qualifiers to a List.”

14.20. Matching a Wildcard PatternYou want to match any number of characters to a field.

TechniqueUse the LIKE operator with the % character to match a wildcard pattern.

<cfquery datasource=”cfcookbook” name=”juniors”>

SELECT Name

FROM employees

19 0672324628 CH14 6/8/05 11:09 AM Page 196

Page 220: ColdFusion MX Developer's Cookbook (Developer's Library)

19714.21. Matching a Single Character

WHERE Name LIKE ‘%Jr.’

</cfquery>

<cfdump var=”#juniors#”>

CommentsThe LIKE operator in SQL allows you to match wildcard patterns against text fields inyour database.The first wildcard is the % character, used to denote a string of zero ormore characters.Table 14.8 explains the meaning of other wildcards available in SQL.The code in this listing will return any name that ends in Jr., which should find every-one in the database that is a junior.

Table 14.8 Wildcards for the LIKE Operator

Wildcard Meaning

% Match a string of zero or more characters

_ Match any single character

[xyz] Match x, y, or z once

[a-z] Match any character between and including a through z

[^xyz] Match any character but x, y, or z

[^a-z] Match any character not between a and z

* Microsoft Access equivalent to %? Microsoft Access equivalent to _

Take note that Microsoft Access uses * and ? for % and _ respectively; however, the syn-tax for [] is the same.

14.21. Matching a Single CharacterYou want to match any single character in a field.

TechniqueUse the _ character with the LIKE operator to match a single character.

<cfquery datasource=”cfcookbook” name=”bobOrRob”>

SELECT Name

FROM employees

WHERE Name LIKE ‘_ob’

</cfquery>

<cfdump var=”#bobOrRob#”>

19 0672324628 CH14 6/8/05 11:09 AM Page 197

Page 221: ColdFusion MX Developer's Cookbook (Developer's Library)

198 Chapter 14 Structured Query Language (SQL)

CommentsBecause the _ character will match just one character, this query will match Bob or Rob.The query will not match Robert, because the pattern only accepts three characternames.The pattern ‘_ob%’ would match Robert.

14.22. Matching a Group of CharactersYou want to match a set of possible characters in a field.

TechniqueUse the [] characters with the LIKE operator to match a range of characters.

<cfquery datasource=”cfcookbook” name=”aNames”>

SELECT Name

FROM employees

WHERE Name LIKE ‘[Aa]%’

</cfquery>

<cfdump var=”#aNames#”>

CommentsThe [] bracket characters are used to hold several characters that can occur in the posi-tion that the brackets appear in the pattern.This query matches names that begin with Aor a.

14.23. Matching a Range of CharactersYou want to match within a range of characters in a field.

TechniqueUse the [] characters with a - (dash) in the LIKE operator to match a range of charac-ters.

<cfquery datasource=”cfcookbook” name=”aToK”>

SELECT Name

FROM employees

WHERE Name LIKE ‘[A-Ka-k]%’

</cfquery>

<cfdump var=”#aToK#”>

19 0672324628 CH14 6/8/05 11:09 AM Page 198

Page 222: ColdFusion MX Developer's Cookbook (Developer's Library)

19914.25. Excluding a Range of Characters

CommentsThis query matches any name that begins with any letter, within the range A through K(in upper- or lowercase).This effectively matches the first half of the alphabet.The dash- character is used to represent the range.

14.24. Excluding a Group of CharactersYou want to match any characters, except those specified, to a field.

TechniqueInclude the ^ character at the beginning of the bracketed text to exclude charactersfrom the pattern.

<cfquery datasource=”cfcookbook” name=”noBobs”>

SELECT Name

FROM employees

WHERE Name LIKE ‘[^Bb]ob%’

</cfquery>

<cfdump var=”#noBobs#”>

CommentsThis query will match Rob, but will not match Bob or bob.This query will match anyname that doesn’t start with B or b followed by ob.

14.25. Excluding a Range of CharactersYou want to match any characters, except those within a specified range, to afield.

TechniqueInclude the ^ character within the brackets before a range to exclude the range from thepattern.

<cfquery datasource=”cfcookbook” name=”noNumbers”>

SELECT Name

FROM employees

WHERE Name LIKE ‘[^0-9]%’

</cfquery>

<cfdump var=”#noNumbers#”>

19 0672324628 CH14 6/8/05 11:09 AM Page 199

Page 223: ColdFusion MX Developer's Cookbook (Developer's Library)

200 Chapter 14 Structured Query Language (SQL)

CommentsThis query returns all names that do not start with a number.The ^ character is used toexclude the range from the pattern.

14.26. Using Prepared StatementsYou want to improve database performance on frequently executed querieswithout storing code on the database.

TechniqueUse the <cfqueryparam> tag to specify a bind parameter.

<cfquery datasource=”cfcookbook” name=”myQuery”>

SELECT Name, Age, Salary

FROM employees

WHERE EmployeeID = <cfqueryparam

cfsqltype=”CF_SQL_INTEGER”

value=”#EmployeeID#”>

</cfquery>

CommentsWhen a SQL statement is to be processed by the database engine, it must first parse theSQL statement to create an execution plan.The execution plan is created based on howthe table is stored internally, which fields are indexed, and so on. Because this operationtakes valuable milliseconds, several databases store a cache of execution plans.

Most queries executed in ColdFusion applications have dynamic variables in them.

SELECT Name, Age, Salary

FROM employees

WHERE EmployeeID = #EmployeeID#

The variable EmployeeID can potentially represent thousands of values. Each time thisquery is executed with a different EmployeeID, your database server sees it as a differentquery.Although technically each query is in fact different, you can see that the query isthe same except for the variables. Fortunately, there is a way to relay this information tothe database so it can cache just one query, instead of thousands of slightly differentqueries.

Typically, the databases that maintain a cache of execution plans also allow you to tellthe database where dynamic variables are in the SQL so that it can cache just one exe-cution plan.This is where the performance benefits come in to play. Smaller cachesmean efficient retrieval, and because the cache size is finite, they allow all possiblequeries to be cached. SQL statements that notify the database where variables exist in

19 0672324628 CH14 6/8/05 11:09 AM Page 200

Page 224: ColdFusion MX Developer's Cookbook (Developer's Library)

20114.26. Using Prepared Statements

the query are known as prepared statements.The actual syntax to bind parameters to theSQL can vary between vendors, but ColdFusion allows you to write vendor-neutralqueries with the <cfqueryparam> tag.

At a minimum, you should pass the <cfqueryparam> tag a CFSQLTYPE, which isused for data type validation, and a value.There are several data types that you can use,outlined in Table 14.9.

Table 14.9 CFSQLTYPES for CFQUERYPARAM

CFSQLTYPE

CF_SQL_BIGINT

CF_SQL_BIT

CF_SQL_BLOB

CF_SQL_CHAR

CF_SQL_CLOB

CF_SQL_DATE

CF_SQL_DECIMAL

CF_SQL_DOUBLE

CF_SQL_FLOAT

CF_SQL_IDSTAMP

CF_SQL_INTEGER

CF_SQL_LONGVARCHAR

CF_SQL_MONEY

CF_SQL_MONEY4

CF_SQL_NUMERIC

CF_SQL_REAL

CF_SQL_REFCURSOR

CF_SQL_SMALLINT

CF_SQL_TIME

CF_SQL_TIMESTAMP

CF_SQL_TINYINT

CF_SQL_VARCHAR

Besides adding a performance boost, using <cfqueryparam> also improves securitywith its data type validation.The security vulnerability that it protects against is a seriousone, and is covered in detail in Appendix B,“Security.” Even if your database doesn’tsupport prepared statements, it’s still a good idea to use <cfqueryparam> in all queriesfor its security protection.

Using <cfqueryparam> has many of the same benefits as using stored procedures;however, they allow your SQL code to be stored within the application code (CFML).Bind parameters are a simple way you can increase your query performance and security

19 0672324628 CH14 6/8/05 11:09 AM Page 201

Page 225: ColdFusion MX Developer's Cookbook (Developer's Library)

202 Chapter 14 Structured Query Language (SQL)

without implementing stored procedures. Stored procedures do however offer much bet-ter security and performance benefits; they are discussed in Chapter 15,“StoredProcedures.”

19 0672324628 CH14 6/8/05 11:09 AM Page 202

Page 226: ColdFusion MX Developer's Cookbook (Developer's Library)

15Stored Procedures

15.0. IntroductionBeginning and intermediate developers often avoid writing stored procedures.Althoughthey can be very complex, in most cases they don’t take much more work than a SQLquery.The potential benefits of using stored procedures outweigh the extra work it takesto implement them.

Stored procedures allow you to encapsulate database queries and other logic into oneprocedure.The procedure may take input parameters, and may return a result, similar toColdFusion user-defined functions.

Procedures are stored on the database server (instead of on your application serverCFM files), hence the name stored procedures. Stored procedures can be written in severallanguages. Microsoft SQL Server supports stored procedures written in C++ and C#;Oracle and DB2 support stored procedures written in Java. Stored procedures are typi-cally written in a language that is specific to the database server.Transact-SQL (or T-SQL) is commonly used with Microsoft SQL Server, whereas PL/SQL is frequently usedwith Oracle.

All that flexibility is great, but you’re probably thinking:“What’s in it for me?” Itturns out that stored procedures have several benefits, including enhanced performance,better security, and code reuse.

Stored procedures increase query performance in two ways—first by caching queryexecution plans for the procedure and second by reducing communication between thedatabase and your application. Stored procedures can also improve your overall applica-tion performance by including business logic that might have ended up in yourColdFusion code.

The code to call a procedure is usually much smaller than the SQL it will execute;this reduces the traffic sent to the database server. Because stored procedures can manip-ulate multiple queries, and only return the data you need, they can eliminate multiple

20 0672324628 CH15 6/8/05 11:09 AM Page 203

Page 227: ColdFusion MX Developer's Cookbook (Developer's Library)

204 Chapter 15 Stored Procedures

trips to the server. Streamlined communication between the database server and applica-tion server improves performance, especially in the presence of simultaneous requests.Stored procedures make it easy to enforce a tight security policy on the database server.Database users can be restricted to execute only a few stored procedures rather than exe-cute SELECT, INSERT, UPDATE, or DELETE commands.The use of stored proceduresalso eradicates the possibility of URL injection hacking (covered in Appendix B,“Security.”).

If you’re using stored procedures, you will never have to write the same SQL querytwice.The same stored procedure can be used across all applications accessing the data-base, making code reuse a benefit that makes your job easier.

Because procedures are stored on the database server, changes to table or columnnames can easily be propagated to the procedures on the server. If your applicationmakes use of stored procedures, you can even change database engines without changinga single line of ColdFusion code.

Hopefully, by now you can see why you should start using stored procedures if yourdatabase supports them.

Because stored procedures can do just about anything, this chapter keeps it simple.You will learn enough to convert current queries to stored procedures.To do morecomplicated tasks, you need to get a book written specifically for your database engine.

The examples in this chapter use the database tables presented in the introduction ofChapter 14,“Structured Query Language (SQL).”

15.1. Writing a Simple Stored Procedure inMicrosoft SQL Server

You want to create a stored procedure in Microsoft SQL Server.

TechniqueUse a CREATE PROCEDURE statement to define a stored procedure.

CREATE PROCEDURE giveRaise AS

UPDATE employees

SET Salary = Salary * 1.05

CommentsThe CREATE PROCEDURE statement tells the database that you are defining a new pro-cedure, similar to how the <cffunction> tag tells ColdFusion that you are defining anew function.

The name of the procedure is specified after CREATE PROCEDURE. Because the SQLwill not be stored in your CFML file, stored procedure names should be descriptiveenough so that you can easily tell what the procedure is doing without looking at the

20 0672324628 CH15 6/8/05 11:09 AM Page 204

Page 228: ColdFusion MX Developer's Cookbook (Developer's Library)

procedure code.This will improve the readability of your ColdFusion code.Chapter 14 talked about the AS keyword, and how it could be used to make aliases totable and column names. Here, AS is used a little differently; it’s used to mark the begin-ning of the procedure body.

Inside the procedure body, you can simply write SQL statements.The SQL statementin the giveRaise stored procedure gives a five percent raise to all employees.This stored procedure only took one more line of code than its SQL counterpart.Therest of the procedures in this chapter won’t be as easy as this one; however, they alsowon’t be much more difficult. So forget all your unfounded fears of stored proceduresand let’s roll!

15.2. Writing a Simple Stored Procedure in Oracle

You want to create a stored procedure in Oracle.

TechniqueUse the CREATE OR REPLACE along with AS, BEGIN, and END to define a stored pro-cedure in Oracle.

CREATE OR REPLACE PROCEDURE giveRaise

AS

BEGIN

UPDATE employees

SET Salary = Salary * 1.05;

END;

CommentsThe syntax for creating the giveRaise stored procedure in Oracle differs slightly fromthe Microsoft SQL Server equivalent.The first difference is the OR REPLACE part of theCREATE PROCEDURE statement. OR REPLACE tells the database to replace the proce-dure definition for giveRaise if one already exists in the database. OR REPLACE isoptional; however, it is handy for testing and making changes to stored procedures.Stored procedure definitions in Oracle use the BEGIN and END keywords to define thebeginning and the end of the procedure body. Oracle also uses the AS keyword just likeMicrosoft SQL Server.

Although the code for the giveRaise procedure is fairly similar on Oracle andMicrosoft SQL Server, as your procedures begin to do more, they will differ quite a bitbetween database engines.

20515.2. Writing a Simple Stored Procedure in Oracle

20 0672324628 CH15 6/8/05 11:09 AM Page 205

Page 229: ColdFusion MX Developer's Cookbook (Developer's Library)

206 Chapter 15 Stored Procedures

15.3. Invoking a Simple Stored ProcedureYou want to call an existing stored procedure in a database.

TechniqueUse the <cfstoredproc> tag to invoke a stored procedure and use the<cfstoredproc> tag to assign the result of the procedure to a query object.

<cfstoredproc datasource=”cfcookbook” procedure=”getEmployeeNames”>

<cfprocresult name=”employeeNames”>

</cfstoredproc>

<b>Employees:</b>

<ul>

<cfoutput query=”employeeNames”>

<li>#employeeNames.Name#</li>

</cfoutput>

</ul>

<cfoutput>#employeeNames.recordcount#</cfoutput> Employee Names returned.

Here is the getEmployeeNames procedure:

CREATE PROCEDURE getEmployeeNames

AS

SELECT Name

FROM employees

CommentsIn this technique, you define a new stored procedure with Microsoft SQL Server syntaxthat returns a result set.The procedure returns the same result as the first SQL query insection 1 of Chapter 14—the names of all the employees.

This example executes the getEmployeeNames procedure with the <cfstoredproc> tag. It uses <cfstoredproc> in its simplest form, by simply specify-ing the datasource and procedure name.The <cfstoredproc> tag has many of thesame attributes as the <cfquery> tag; a complete listing of attributes can be found inTable 15.1.

Another way of executing stored procedures is by using T-SQL’s EXECUTE command.The getEmployeeNames procedure can be called from EXECUTE with this SQL statement: EXECUTE getEmployeeNames.

20 0672324628 CH15 6/8/05 11:09 AM Page 206

Page 230: ColdFusion MX Developer's Cookbook (Developer's Library)

20715.4. Writing a Stored Procedure with Parameters in Microsoft SQL Server

Table 15.1 <cfstoredproc> Attributes

Attribute Notes

procedure The name of the procedure to execute.

datasource The datasource that contains the procedure.

username The database username.

password The database password.

blockfactor The maximum number of rows to return from the server in one block.Default is 1. Can be used to improve performance.

debug If true, displays debugging information for the procedure.returncode If true, sets the value of the cfstoredproc.statuscode variable to the

procedure’s native return code.

The <cfprocresult> tag allows you to assign a variable name to the query object returned from the stored procedure.There is nothing special about the queryobject returned from the procedure, treat it no differently than you would treat a query object returned from the <cfquery> tag.All of the attributes for <cfprocresult> can be found in Table 15.2.

Table 15.2 <cfprocresult> attributes

Attribute Notes

name The name of a variable to assign the result set query to.

resultset Used to identify a result set when more than one result sets are returnedfrom a procedure.The default value is 1.

maxrows The maximum number of rows to return from the procedure.The defaultvalue is –1, which allows an unlimited number of rows to be returned.

When you access a stored procedure from ColdFusion, the database user ColdFusion isusing must have EXECUTE or EXEC permission for that stored procedure.

15.4. Writing a Stored Procedure withParameters in Microsoft SQL Server

You want to pass input values to your procedure in SQL Server.

TechniqueUse a list of @variableName datatype values to define the input parameters of yourprocedure.

CREATE PROCEDURE addEmployee

@name varchar(50),

20 0672324628 CH15 6/8/05 11:09 AM Page 207

Page 231: ColdFusion MX Developer's Cookbook (Developer's Library)

208 Chapter 15 Stored Procedures

@age int,

@salary money,

@deptID int

AS

INSERT INTO employees (Name, Age, Salary, DepartmentID)

VALUES(@name, @age, @salary, @deptID)

CommentsInput parameters are defined similarly to how you might define arguments for a func-tion.The variable name is prefixed with an @ symbol, and followed by a data type.

Unlike ColdFusion functions, stored procedures require that you specify a data typefor the input parameters. CFML is a loosely typed language, but several languages, suchas Java and C#, are not.You need to be concerned about types in databases becauseother languages besides CFML can potentially access the same procedure.

The SQL statement refers to the variable with the @ prefix, similar to how you wrapvariables with # symbols inside the <cfoutput> tag. Notice that you don’t need towrap single quotes around the @name variable because the stored procedure knows itsdata type.

15.5. Writing a Stored Procedure withParameters in Oracle

You want pass input values to your procedure in Oracle.

TechniqueEnclose the parameters in parentheses after the procedure name to define input parame-ters in Oracle.

CREATE OR REPLACE PROCEDURE addEmployee (name IN varchar2,

age IN number,

salary IN number,

deptID IN number)

AS

BEGIN

INSERT INTO employees (Name, Age, Salary, DepartmentID)

VALUES(name,age,salary, deptID);

END;

20 0672324628 CH15 6/8/05 11:09 AM Page 208

Page 232: ColdFusion MX Developer's Cookbook (Developer's Library)

20915.6. Invoking a Stored Procedure with Parameters

CommentsThe parameters in an Oracle stored procedure are enclosed in parentheses. UnlikeMicrosoft SQL Server, @ signs are not used to prefix variable names.

The IN keyword occurs after the variable name. Chapter 14 discussed how the INkeyword can be used to specify a list of possible values for a particular column. Here, youuse IN to define the parameter as an input parameter. Note that the IN keyword,depending on its context, can be used for two completely different purposes in PL/SQL.

The data type of the parameter is placed after the IN keyword.Variables in PL/SQL don’t use an identifier like the @ symbol in T-SQL, so when you

use parameters in this SQL, it can be confusing as to which words are variables andwhich words are part of the SQL. In this technique, Name is used twice in the SQLstatement (they use different case, but PL/SQL is not case sensitive). Fortunately, Oracleis smart enough to know that the first instance of Name is referring to a column name,and the second to a variable name.

15.6. Invoking a Stored Procedure withParameters

You want to pass variables into your stored procedure.

TechniqueUse the <cfprocparam> tag to pass variables into the stored procedure.

<cfif IsDefined(“form.name”)>

<!--- make sure all form variables are defined --->

<cfparam name=”form.age” type=”numeric” default=”0”>

<cfparam name=”form.salary” type=”numeric” default=”0”>

<cfparam name=”form.departmentID” type=”numeric” default=”0”>

<!--- run the addEmployee procedure --->

<cfstoredproc datasource=”cfcookbook” procedure=”addEmployee”>

<cfprocparam value=”#form.name#” cfsqltype=”CF_SQL_VARCHAR” type=”in”>

<cfprocparam value=”#form.age#” cfsqltype=”CF_SQL_INTEGER” type=”in”>

<cfprocparam value=”#form.salary#” cfsqltype=”CF_SQL_MONEY” type=”in”>

<cfprocparam value=”#form.departmentID#” cfsqltype=”CF_SQL_INTEGER”

type=”in”>

</cfstoredproc>

Employee Added.

</cfif>

<!--- get list of departments: Name, and DepartmentID --->

<cfstoredproc datasource=”cfcookbook” procedure=”getDepartments”>

<cfprocresult name=”depts”>

</cfstoredproc>

20 0672324628 CH15 6/8/05 11:09 AM Page 209

Page 233: ColdFusion MX Developer's Cookbook (Developer's Library)

210 Chapter 15 Stored Procedures

<b>Add New Employee</b>

<form method=”post”>

Name: <input type=”text” name=”name”><br>

Age: <input type=”text” name=”name” size=”3”><br>

Salary: <input type=”text” name=”name”><br>

Department:

<select name=”departmentID”>

<cfoutput query=”depts”>

<option value=”#depts.DepartmentID#”>#depts.Name#</option>

</cfoutput>

</select>

<br>

<input type=”submit” value=”Add Employee”>

</form>

Here is the getDepartments procedure:

CREATE PROCEDURE getDepartments

AS

SELECT DepartmentID, Name

FROM departments

CommentsThis example calls the addEmployee procedure defined in sections 15.4 and 15.5,which has four input parameters. Parameters are passed to stored procedures by placing<cfprocparam> tags inside the <cfstoredproc> tag.The <cfprocparam> tagsshould be placed in the same order as the parameters are defined in the stored proce-dure.

The Name, Age, Salary, and DepartmentID form variables are passed into thevalue attribute of the <cfprocparam> tag.The cfsqltype attribute allowsColdFusion to validate the data type passed in to the value attribute.A listing of allcfsqltype data types is available in Table 14.9.The type attribute for <cfproc-param> tells ColdFusion that the parameter in this case is an input parameter.You’lllearn about output parameters in the next section.Table 15.3 lists all attributes for the<cfprocparam> tag.

Table 15.3 <cfprocparam> Attributes

Attribute Notes

cfsqltype The data type of the parameter. See Table 14.9 for a list of possible values.

type IN, OUT, or INOUT, depending on whether the parameter is passing in a vari-able, setting a variable, or doing both.

value The value of an IN or INOUT parameter.

variable The variable name for the result of an OUT or INOUT parameter.

20 0672324628 CH15 6/8/05 11:09 AM Page 210

Page 234: ColdFusion MX Developer's Cookbook (Developer's Library)

maxlength The maximum length of a parameter.

scale The number of decimal places to scale the parameter to.null Used to pass a NULL value in an input parameter.The value attribute will be

ignored if this attribute is set to true.

To return all the DepartmentIDs and department names from the departments table, theexample uses another stored procedure called getDepartments.ThegetDepartments procedure is used in the add employee form to construct a list of allpossible departments.

15.7. Using Output ParametersYou want your stored procedure to return a variable.

TechniqueUse the OUTPUT keyword to declare a parameter as an output parameter, and thenretrieve the value of the variable with <cfprocparam> by setting the type attribute to“out”.

CREATE PROCEDURE addEmployee

@name varchar(50),

@age int,

@salary money,

@deptID int,

@EmployeeID int OUTPUT

AS

INSERT INTO employees (Name, Age, Salary, DepartmentID)

VALUES(@name, @age, @salary, @deptID)

SELECT @EmployeeID = @@IDENTITY

<cfif IsDefined(“form.name”)>

<!--- make sure all form variables are defined --->

<cfparam name=”form.age” type=”numeric” default=”0”>

<cfparam name=”form.salary” type=”numeric” default=”0”>

<cfparam name=”form.departmentID” type=”numeric” default=”0”>

<!--- run the addEmployee procedure --->

<cfstoredproc datasource=”cfcookbook” procedure=”addEmployee”>

<cfprocparam value=”#form.name#” cfsqltype=”CF_SQL_VARCHAR” type=”in”>

21115.7. Using Output Parameters

Table 15.3 Continued

Attribute Notes

20 0672324628 CH15 6/8/05 11:09 AM Page 211

Page 235: ColdFusion MX Developer's Cookbook (Developer's Library)

212 Chapter 15 Stored Procedures

<cfprocparam value=”#form.age#” cfsqltype=”CF_SQL_INTEGER” type=”in”>

<cfprocparam value=”#form.salary#” cfsqltype=”CF_SQL_MONEY” type=”in”>

<cfprocparam value=”#form.departmentID#” cfsqltype=”CF_SQL_INTEGER”

type=”in”>

<cfprocparam variable=”EmpID” cfsqltype=”CF_SQL_INTEGER” type=”OUT”>

</cfstoredproc>

Your Employee ID is <cfoutput>#EmpID#</cfoutput>.

</cfif>

<!--- get list of departments: Name, and DepartmentID --->

<cfstoredproc datasource=”cfcookbook” procedure=”getDepartments”>

<cfprocresult name=”depts”>

</cfstoredproc>

<b>Add New Employee</b>

<form method=”post”>

Name: <input type=”text” name=”name”><br>

Age: <input type=”text” name=”name” size=”3”><br>

Salary: <input type=”text” name=”name”><br>

Department:

<select name=”departmentID”>

<cfoutput query=”depts”>

<option value=”#depts.DepartmentID#”>#depts.Name#</option>

</cfoutput>

</select>

<br>

<input type=”submit” value=”Add Employee”>

</form>

CommentsBy adding the OUTPUT keyword to the end of a parameter declaration in the stored pro-cedure in T-SQL, the parameter’s value can be read by ColdFusion after the query hasexecuted.The new addEmployee procedure returns the employee ID of the employeewho was added by the procedure.This is done by setting the output variable@EmployeeID to the built-in variable @@IDENTITY, after the INSERT statement.The@@IDENTITY variable holds the value of the employee ID generated automatically bythe INSERT statement.

The <cfprocparam> tag tells ColdFusion that you want to read the value of thisparameter after the procedure executes by setting the type attribute to “out”.The vari-able attribute of <cfprocparam> allows you to assign a ColdFusion variable name tothe parameter so you can use it later in your code.

In Oracle PL/SQL, the OUT keyword is used instead of OUTPUT.The keyword isplaced before the data type in the parameter definition.

20 0672324628 CH15 6/8/05 11:09 AM Page 212

Page 236: ColdFusion MX Developer's Cookbook (Developer's Library)

21315.8. Working with Multiple Result Sets

15.8. Working with Multiple Result SetsYou want to use a stored procedure that returns more than one result set.

TechniqueUse multiple <cfprocresult> tags to assign names to each result set.

CREATE PROCEDURE getDepartmentsAndProjects

AS

SELECT Name

FROM departments

SELECT Name

FROM projects

<cfstoredproc datasource=”cfcookbook”

procedure=”getDepartmentsAndProjects”>

<cfprocresult name=”dept” resultset=”1”>

<cfprocresult name=”proj” resultset=”2”>

</cfstoredproc>

<cfdump var=”#dept#” label=”Department Names”>

<cfdump var=”#proj#” label=”Project Names”>

CommentsStored procedures may return more than one result set upon execution, involving fewertrips to the database server. Such a model can be more efficient than using multiple pro-cedures to return multiple result sets.

Such a procedure is defined in this section.The getDepartmentsAndProjectsstored procedure is defined using SQL Server syntax to return two result sets.The firstresult set lists the department names and the second is a list of project names.The resultsets are returned in the order that they are defined.

You can apply a variable name to each result set using <cfprocresult> tags.Theresultset attribute of the <cfprocresult> tag tells ColdFusion which set to assignthe variable name to.

NoteBecause the default value of the resultset attribute is 1, the attribute is not required on the first

<cfprocresult> tag. It is however a good idea to use the resultset attribute for readability when

using multiple result sets.

20 0672324628 CH15 6/8/05 11:09 AM Page 213

Page 237: ColdFusion MX Developer's Cookbook (Developer's Library)

20 0672324628 CH15 6/8/05 11:09 AM Page 214

Page 238: ColdFusion MX Developer's Cookbook (Developer's Library)

VLanguage Extensibility Features

16 User-Defined Functions

17 ColdFusion Custom Tags

18 CFX API Custom Tags

19 Components

20 Objects

21 WDDX

22 XML

23 Web Services

24 J2EE Interoperability

21 0672324628 Part 05 6/8/05 11:09 AM Page 215

Page 239: ColdFusion MX Developer's Cookbook (Developer's Library)

21 0672324628 Part 05 6/8/05 11:09 AM Page 216

Page 240: ColdFusion MX Developer's Cookbook (Developer's Library)

16User-Defined Functions

16.0. IntroductionUser-defined functions (UDFs) were one of the most anticipated features of ColdFusion5. It didn’t take long, however, for ColdFusion developers to discover the limitations ofuser-defined functions in ColdFusion 5. User-defined functions in ColdFusion 5 had tobe defined within <cfscript> tags.This meant that your user-defined functionscouldn’t use any ColdFusion tags, only functions. In ColdFusion 5, your creativity waslimited to the extent of the built-in function library.

With the introduction of the <cffunction> tag in ColdFusion MX, developers canleverage all the features of ColdFusion within UDFs.The <cffunction> tag allowsyou to use tags within your user-defined function. It also allows you to enforce data-typevalidation, and the existence of input arguments, as well as enforcing the data type ofreturn values. Because of the improvements of <cffunction>, you will use its syntaxexclusively in this chapter.The syntax for creating <cfscript> user-defined functionsis covered in Appendix D,“Converting Between Tags and Scripting.”

Although user-defined functions are powerful, there are certain tasks that are best leftto the other language constructs, such as ColdFusion custom tags (covered in Chapter17,“ColdFusion Custom Tags”) and ColdFusion components (covered in Chapter 19“Components”).

User-defined functions work well for manipulating a variable and returning sometranslation of that variable. For instance, you might create a UDF called removeSpacesthat removes all spaces from a string.

User-defined functions don’t work as well for generating HTML content. Forinstance, rather than creating a user-defined function to display a copyright message, youmight create a custom tag or <cfinclude> a template.

Also rather than developing several related user-defined functions to perform similaroperations on the same piece of data, you can create a ColdFusion component.The ben-efit of using a component in this case is that the shared data can persist through severalfunction calls.

22 0672324628 CH16 6/8/05 11:09 AM Page 217

Page 241: ColdFusion MX Developer's Cookbook (Developer's Library)

218 Chapter 16 User-Defined Functions

16.1. Declaring a FunctionYou want to define a simple function.

TechniqueUse the <cffunction> tag to define a user-defined function. Use <cfreturn> toreturn a value from the function.

<cffunction name=”IsIE” returntype=”boolean”>

<cfif CGI.USER_AGENT contains “MSIE”>

<cfreturn true>

<cfelse>

<cfreturn false>

</cfif>

</cffunction>

<cfif IsIE()>

You Are using Microsoft Internet Explorer!

<cfelse>

You Are not using Microsoft Internet Explorer!

</cfif>

CommentsThis example created a user-defined function that returns true if the client browser isMicrosoft Internet Explorer and false otherwise.

The <cffunction> tag tells ColdFusion that you are declaring a function; inside thetag resides the CFML code that is executed when the function is called. <cffunction>has several attributes but only name is required.The name attribute, as you might expect,defines the name you use to call your user-defined function. Just like variable names inColdFusion, function names are not case sensitive. Function names follow the same rulesas variable names; the only limitation is that you cannot define a function with the samename as an existing function (both built-in, and user-defined functions).

Although name is the only required attribute, it’s a good idea to use the returntypeattribute. If your UDF does not return anything, you can set returntype equal tovoid.The return type can also be set to any of the values listed in Table 16.1.

Table 16.1 Function Data Types

Return Type Meaning

string Covers all simple variables such as numbers, booleans, and lists, as well asplain text strings.

boolean A string or number that can be reduced to true or false.

22 0672324628 CH16 6/8/05 11:09 AM Page 218

Page 242: ColdFusion MX Developer's Cookbook (Developer's Library)

21916.1. Declaring a Function

numeric Any string that can be evaluated as a number.

struct A ColdFusion structure.

query A ColdFusion query object.

variableName Any string that matches the rules for a ColdFusion variable name (nospaces, and so on).

void The function does not return a value.

array A ColdFusion array.

date A ColdFusion date object.

binary Binary data.

any Anything; this is the default.

guid A globally unique identifier.

uuid A universally unique identifier.componentName The name of any ColdFusion component.

Table 16.2 contains a complete listing of the attributes for the <cffunction> tag.

Table 16.2 <cffunction> Tag Attributes

Attribute Meaning

name The name of the function; required.

returntype The data type that the function will return, see Table 16.1 for possible val-ues. Required when implementing a Web service, and highly recommend-ed otherwise.

output When set to true, the contents of the <cffunction> tag are effectivelywrapped with a <cfoutput> tag.When false, <cffunction> wraps thecontent with a <cfsilent> tag. Note the ColdFusion documentationspecifies that this attribute only works when <cffunction> is used in aColdFusion component; however, we have found it to work for UDFs aswell.

roles A list of role names that have permission to execute the function. SeeChapter 13,“User Authentication and Authorization,” for more informa-tion on roles.

access Used in components; valid values are private, public, package, andremote. See Chapter 19 for more information.

hint A string that describes the function; used only in ColdFusion compo-nents.

When you have a result to return from the function, you use the <cfreturn> tag.Returning variables is described in detail in section 3 of this chapter.

How do you call a UDF? By its name of course. UDFs are called just like you do abuilt-in ColdFusion function such as IsDefined() or Len().

Table 16.1 Continued

Return Type Meaning

22 0672324628 CH16 6/8/05 11:09 AM Page 219

Page 243: ColdFusion MX Developer's Cookbook (Developer's Library)

220 Chapter 16 User-Defined Functions

16.2. Function ArgumentsYou want to pass an input value to your function.

TechniqueUse the <cfargument> tag to define function arguments.

<cffunction name=”Split” returntype=”array”>

<cfargument name=”str” type=”string” required=”true”>

<cfargument name=”size” type=”numeric” required=”false” default=”5”>

<cfset pos = 1>

<cfset strLen = Len(arguments.str)>

<cfset result = ArrayNew(1)>

<cfloop condition=”pos LTE strLen”>

<cfset subString = Mid(arguments.str, pos, arguments.size)>

<cfset ArrayAppend(result, subString)>

<cfset pos = pos + arguments.size>

</cfloop>

<cfreturn result>

</cffunction>

<cfdump var=”#Split(“1234567890”)#” label=”Result of split function”>

CommentsThe <cfargument> tag allows you to define not only the name of an argument, butalso its data type, default values, and an option to specify whether the argument isrequired. Because you cannot specify such options with UDFs in <cfscript>, this isone of the reasons it’s good to use the <cffunction> syntax.The attributes for the<cfargument> tag are defined in Table 16.3.

Table 16.3 <cfargument> Tag Attributes

Return Type Meaning

name The name of the argument; required.

type The data type that the input value must be; see Table 16.2 for possible values.This value defaults to any, but is highly recommended.

required If true, the argument must be present when the function is called. If false, theattribute can be omitted.

default The value to use when the argument was not passed into the function.

22 0672324628 CH16 6/8/05 11:09 AM Page 220

Page 244: ColdFusion MX Developer's Cookbook (Developer's Library)

22116.2. Function Arguments

The example Split function takes a string, and optionally a size, and returns an array ofsubstrings that are of the size specified.The size argument is not required and thedefault size is 5, so when you call the split with the string 1234567890, it returns anarray with two elements the first 012345 and the second 67890.

As you might have assumed, the order of <cfargument> tags is important.The orderthat the tags show up is the same as the order that arguments are used in the UDF call.

The value of an argument can be accessed using structure dot notation (arguments.argumentName), and also as an array. Using arguments as an array allowsyou to write functions that take in an unknown number of arguments.The followingcode shows the Split function illustrating this point:

<cffunction name=”SuperSplit” returntype=”array”>

<cfargument name=”str” type=”string” required=”true”>

<cfset pos = 1>

<cfset result = ArrayNew(1)>

<cfset argLen = ArrayLen(arguments)>

<cfset strLen = Len(arguments.str)>

<!--- they didn’t pass in any numbers, return entire string --->

<cfif argLen LT 2>

<cfset ArrayAppend(result, arguments.str)>

<cfreturn result>

</cfif>

<cfloop from=”2” to=”#argLen#” index=”i”>

<cfset subStringLength = arguments[i]>

<cfset subString = Mid(arguments.str, pos, subStringLength)>

<cfset ArrayAppend(result, subString)>

<cfset pos = pos + subStringLength>

</cfloop>

<!--- if there are leftovers add them to the end --->

<cfif pos LT strLen>

<cfset ArrayAppend(result, Right(arguments.str, strLen-pos+1))>

</cfif>

<cfreturn result>

</cffunction>

<!--- split up a phone number into an array --->

<cfdump var=”#SuperSplit(“555-555-1324”,3,1,3,1,4)#” label=”Result of SuperSplitUDF”>

The SuperSplit function allows you to pass in multiple lengths at which to split thestring.This example passes in a phone number, 555-555-1234, and the lengths 3, 1, 3,1, and 4.The result is an array with elements 555, -, 555, -, and 1234.This functionwould allow you to easily reformat the phone number or any other data that is stored ina known format.

22 0672324628 CH16 6/8/05 11:09 AM Page 221

Page 245: ColdFusion MX Developer's Cookbook (Developer's Library)

16.3. Returning ValuesYou want the function to return a value.

TechniqueUse the <cfreturn> tag to return a result from a user-defined function.

<cffunction name=”IsIE” returntype=”boolean”>

<cfreturn CGI.USER_AGENT contains “MSIE”>

</cffunction>

<cfif IsIE()>

You Are using Microsoft Internet Explorer!

<cfelse>

You Are not using Microsoft Internet Explorer!

</cfif>

CommentsThis version of the IsIE function does the same thing as the version presented in sec-tion 1 of this chapter; however, the code used to implement it is much shorter.The<cfreturn> tag can take any expression or variable and return it to the function’scaller. In IsIE, you can use the expression CGI.USER_AGENT contains “MSIE”inside the <cfreturn> tag because its result is effectively the intended result of theIsIE UDF.

16.4. Suppressing OutputYou want to suppress output in your custom function from appearing in yourresponse.

TechniqueUse the output attribute of the <cffunction> tag to control output generated by thefunction.

<cffunction name=”noOutputAttribute” returntype=”void”>

<cfset x = “Value”>

#x#

</cffunction>

<cffunction name=”outputTrue” returntype=”void” output=”true”>

<cfset x = “Value”>

222 Chapter 16 User-Defined Functions

22 0672324628 CH16 6/8/05 11:10 AM Page 222

Page 246: ColdFusion MX Developer's Cookbook (Developer's Library)

22316.5. Recursive Functions

#x#

</cffunction>

<cffunction name=”outputFalse” returntype=”void” output=”false”>

<cfset x = “Value”>

#x#

</cffunction>

<cfoutput>

#noOutputAttribute()# <br>

#outputTrue()# <br>

#outputFalse()#

</cfoutput>

CommentsThis example defines three functions, all with the same body, yet each function outputs adifferent result.The difference in each function is the value or presence of the outputattribute. Let’s explore what each function yields.

The first function, noOutputAttribute, doesn’t specify a value for the outputattribute in the <cffunction> tag. The body of the function is executed just as youmight expect; it simply prints the string #x# because you didn’t place the <cfoutput>tag around the variable.

The next function, outputTrue, sets the output attribute to a value of true.Theoutput of this function is Value.When output is true, the <cffunction> tag automat-ically wraps a <cfoutput> around the body of the function, thus allowing variables tobe evaluated.

The third function does not produce any output because output is false.When output=”false”, <cffunction> wraps the function body with <cfsilent> tags tosuppress output.

Note that all these functions specify a return type of “void”, meaning they don’treturn anything. However, they can output a value to the response. Because functionscan both output a value and return a value, it’s best to always use output=”false”,and stick to custom tags or CFML templates for generating output.

16.5. Recursive FunctionsYou want to write a function that calls itself.

TechniqueMake a call to the function from within the function.

<cffunction name=”Power” returntype=”numeric”>

<cfargument name=”base” type=”numeric” required=”true”>

22 0672324628 CH16 6/8/05 11:10 AM Page 223

Page 247: ColdFusion MX Developer's Cookbook (Developer's Library)

224 Chapter 16 User-Defined Functions

<cfargument name=”exponent” type=”numeric” required=”true”>

<cfif arguments.exponent LT 0>

<cfthrow type=”NegativeExponentException”

message=”You cannot pass a negative exponent to the power function.”>

<cfelseif arguments.exponent EQ 0>

<!--- base case --->

<cfreturn 1>

<cfelse>

<!--- recursive step --->

<cfreturn arguments.base * Power(arguments.base, arguments.exponent-1)>

</cfif>

</cffunction>

2<sup>3</sup> = <cfoutput>#Power(2,3)#</cfoutput>

CommentsThis example defines a function called Power that can be used to calculate the value ofa base number raised to an exponent. For example, to calculate two cubed (23), two ispassed in as the base, and three is passed as the exponent.The value is calculated by mul-tiplying 2 * 2 * 2 or by multiplying 22 * 21 * 20.

The first step to creating a recursive function is to find the base case.The base case isa simple sub-problem that you can solve.This problem has two potential base cases; youknow that x1 is always x, and that x0 is always 1.This algorithm uses x0 as the base case.

Next, you need to define the recursive step.This step keeps recursively calling itselfwith different values until the base case is reached. In the Power function, this isachieved by decrementing the exponent and calling the Power function again.

Like many recursive problems, this problem can be solved iteratively as follows:

<cffunction name=”Power” returntype=”numeric”>

<cfargument name=”base” type=”numeric” required=”true”>

<cfargument name=”exponent” type=”numeric” required=”true”>

<cfif arguments.exponent LT 0>

<cfthrow type=”NegativeExponentException”

message=”You cannot pass a negative exponent to the power function.”>

<cfelseif arguments.exponent EQ 0>

<cfreturn 1>

<cfelse>

<cfset var result = 1>

<cfloop from=”1” to=”#arguments.exponent#” index=”i”>

<cfset result = result * arguments.base>

</cfloop>

<cfreturn result>

</cfif>

</cffunction>

2<sup>3</sup> = <cfoutput>#Power(2,3)#</cfoutput>

22 0672324628 CH16 6/8/05 11:10 AM Page 224

Page 248: ColdFusion MX Developer's Cookbook (Developer's Library)

22516.6. Working with Function References

Although many recursive problems are difficult to convert to iterative ones, this one wasfairly easy. Recursion is typically used because the recursive solution to a problem is easi-er to find than an iterative one.

Iterative solutions typically perform better than recursive solutions due to the over-head of calling a function over and over.The build up of this overhead can often lead toa common problem when using recursive functions, called a stack overflow. Each time youcall a function, the function call is placed on the call stack.As you might imagine, whena recursive function is calling itself thousands of times, this call stack can fill up quickly.One solution to this problem in many languages is to create a function that is tail recursive, meaning the last line in the function is the recursive step (the recursive Powerfunction is tail recursive).Tail recursive functions can be removed from the stack afterthey are called, thus avoiding a stack overflow.

In ColdFusion, tail recursive functions can still cause a stack overflow, so be careful.Try running the recursive Power function with a very large exponent; ColdFusion willreport the stack overflow.

16.6. Working with Function ReferencesYou want to store a reference to a function in a variable.

TechniqueSet a variable to the name of a user defined function.

<cffunction name=”IsIE” returntype=”boolean”>

<cfreturn CGI.USER_AGENT contains “MSIE”>

</cffunction>

<cfset ie = IsIE>

<cfif ie()>

We are using Internet Explorer

<cfelse>

We are not using Internet Explorer

</cfif>

CommentsWhen you define a function, a local variable is created using the name of the function.The variable holds a reference to the function.The function reference can be assigned toanother variable.

In this example, the IsIE function was defined and a reference to the IsIE functionis copied to the variable ie in this line:

<cfset ie = IsIE>

22 0672324628 CH16 6/8/05 11:10 AM Page 225

Page 249: ColdFusion MX Developer's Cookbook (Developer's Library)

226 Chapter 16 User-Defined Functions

When function references are copied to different variables, they are copied by reference,not by value.When a variable is copied by value, an entire copy of the object is copied;when a variable is copied by reference, only a reference (an indicator to the originalobject’s location) to the object is copied.This point is illustrated in the following example:

<cffunction name=”A”>

<cfreturn “A”>

</cffunction>

<cfset reference = A>

<cfoutput>#reference()#</cfoutput><br>

<cffunction name=”B”>

<cfreturn “B”>

</cffunction>

<cfset reference = B>

<cfoutput>#reference()#</cfoutput><br>

<cfset B = A>

<cfoutput>#reference()#</cfoutput><br>

<cfoutput>#B()#</cfoutput><br>

This example outputs the following:A

B

B

A

The crux of this example occurs when a reference to the function A is copied to thevariable B.

<cfset B = A>

The resulting output shows two things. First it shows that the variable B is simply a ref-erence to the function B and not the function itself. Second it shows that the variablesare copied by reference and not by value, because the third line of output displays a Band not an A.

References to user defined functions can be stored in different scopes such as application, server, session, and so fourth. However, when a function is definedit must not have a dot (.) in its name.The following code will throw an exception:

<cffunction name=”application.IsIE” returntype=”boolean”>

<cfreturn CGI.USER_AGENT contains “MSIE”>

</cffunction>

22 0672324628 CH16 6/8/05 11:10 AM Page 226

Page 250: ColdFusion MX Developer's Cookbook (Developer's Library)

22716.6. Working with Function References

The proper way to store a reference to a function in a scope other than the default (thevariable’s scope) is to copy the reference as follows:

<cffunction name=”IsIE” returntype=”boolean”>

<cfreturn CGI.USER_AGENT contains “MSIE”>

</cffunction>

<cfset application.IsIE = IsIE>

22 0672324628 CH16 6/8/05 11:10 AM Page 227

Page 251: ColdFusion MX Developer's Cookbook (Developer's Library)

22 0672324628 CH16 6/8/05 11:10 AM Page 228

Page 252: ColdFusion MX Developer's Cookbook (Developer's Library)

17ColdFusion Custom Tags

17.0. IntroductionGood programming languages should encourage code isolation and encapsulation. Bydissecting your application into small, highly specialized pieces, you can make it easier tomaintain, extend, and debug.

ColdFusion custom tags are the oldest means to encapsulate code in the CFML pro-gramming language. Prior to ColdFusion 5.0, custom tags provided the best (and, for themost part, only) way to group common logic into a reusable code component. Newerversions of ColdFusion have added other extensibility mechanisms. ColdFusion 5.0introduced custom functions to the CFML language and ColdFusion MX includes sup-port for ColdFusion Components (see Chapter 19,“Components”).

Despite these advances in CFML, scripted ColdFusion custom tags are the simplestand most versatile way to create application building blocks.This chapter exploresColdFusion custom tags.You’ll write some tags and look at how these tags can be usedwithin client templates.You’ll also look at topics such as data exchange and the nestingof custom tags.

17.1. Creating a Simple Custom TagYou want to create a simple custom tag.

TechniqueCreate a custom tag by creating a regular ColdFusion template calledhelloWorldTag.cfm:

Hello World!

23 0672324628 CH17 6/8/05 11:10 AM Page 229

Page 253: ColdFusion MX Developer's Cookbook (Developer's Library)

230 Chapter 17 ColdFusion Custom Tags

CommentsAny ColdFusion template can be treated as a custom tag.There is no limit to the func-tionality that your custom tag can implement.The example here shows the simplest ofColdFusion templates; the template merely outputs the string “Hello World!”.

This template can be used as a custom tag if it is placed in the CustomTags folder inthe ColdFusion installation directory or in the same directory as the calling template.The tag created in the previous example is called helloWorldTag.

17.2. Accessing a Custom TagYou want to access an existing custom tag from your ColdFusion application.

TechniqueExecute a custom tag by using the <cf_[tagname]> call syntax.

<html>

<body>

Calling the HelloWorld custom tag...

<cf_helloWorldTag>

</body>

</html>

CommentsThe template in this example acts as a client to the HelloWorldTag custom tag. Notethat you must use the cf_ prefix when calling any custom tag.The result of invokingthe HelloWorldTag custom tag is the insertion of the string “Hello World” into thecalling template.

17.3. Using AttributesYou want to pass CFML data structures to your custom tag.

TechniqueUse the Attributes structure to pass arguments to a custom tag.greetingTag.cfm:

<cfparam name=”Attributes.name” default=”you”>

<cfoutput>

Hello, #Attributes.name#

</cfoutput>

23 0672324628 CH17 6/8/05 11:10 AM Page 230

Page 254: ColdFusion MX Developer's Cookbook (Developer's Library)

23117.4. Returning a Result

greetingClient.cfm:

<cfparam name=”name” default=”Tom”>

<html>

<body>

Calling greeting custom tag...

<cf_greetingTag name=”#name#”>

</body>

</html>

CommentsAttributes are the best way to communicate with your custom tag. In theory, a customtag can use the Caller variable scope to look for variables.This is not good style,though, because it creates a tight coupling between the client and the custom tag andinhibits the tag’s reuse in other applications.

Using attributes in your custom tag is extremely simple. ColdFusion creates animplicit Attributes collection that your custom tag can query to find and extractmandatory and/or optional attributes. In the file greetingTag.cfm, the custom taguses the <cfparam> tag to initialize the optional name attribute. It is a good idea to usethe <cfparam> tag to identify all of the custom tag’s mandatory and/or optional attrib-utes. Declare mandatory attributes by using the <cfparam> tag without the defaultoption to cause ColdFusion to throw an error if the user fails to specify the attribute.Alloptional attributes should be initialized with <cfparam> to some default value, such asthe empty string.Attributes can subsequently be referenced in the custom tag templateby using the Attributes prefix.

Passing attributes from a client to a custom tag is even easier.All you need to do isspecify the attribute name and value in the custom tag reference. For example, the tem-plate greetingClient.cfm calls the <cf_greetingTag> custom tag and passes inthe name attribute with the following line of code:

<cf_greetingTag name=”#name#”>

17.4. Returning a ResultYou want to return a result from your custom tag.

TechniquegetDomainTag.cfm:

<cfparam name=”Attributes.email”>

<cfparam name=”Attributes.name”>

23 0672324628 CH17 6/8/05 11:10 AM Page 231

Page 255: ColdFusion MX Developer's Cookbook (Developer's Library)

232 Chapter 17 ColdFusion Custom Tags

<cfscript>

result = GetToken(Attributes.email,2,”@”);

SetVariable(“Caller.”&Attributes.name,result);

</cfscript>

getDomainClient.cfm:

<cfparam name=”email” default=”[email protected]”>

<html>

<body>

<cf_getDomainTag email=”#email#” name=”domain”>

<cfoutput>

The domain for the email address #email# is #domain#.

</cfoutput>

</body>

</html>

CommentsMost custom tags are not meant to output content. Usually, a custom tag performs anoperation and returns the result to the calling template.The calling template can chooseto display the result, or not.This practice was particularly common before custom func-tions were released in ColdFusion 5.0.

A common design pattern for returning results is the addition of a required “name”or “variable” attribute to the custom tag.This variable contains the name of a variable inthe Caller scope where the custom tag should place its return result.Any ColdFusionprogrammer who has used the <cfquery> tag should recognize this concept.

17.5. Adding Start and End TagsYour custom tag requires a body.

Techniquebiu.cfm:

<cfif ThisTag.executionmode is ‘end’>

<cfset ThisTag.GeneratedContent =

“<b><i><u>#ThisTag.GeneratedContent#</u></i></b>”>

</cfif>

biuClient.cfm:

<html>

<body>

23 0672324628 CH17 6/8/05 11:10 AM Page 232

Page 256: ColdFusion MX Developer's Cookbook (Developer's Library)

23317.5. Adding Start and End Tags

The following text has been formatted by the biu custom tag...

<cf_biu>

<cfoutput>

Today’s date is #DateFormat(Now(),’mm/dd/yyyy’)#.

</cfoutput>

</cf_biu>

</body>

</html>

CommentsColdFusion Custom Tags can have both a start and an end tag.This feature enables youto perform operations on the content between the start and end tags. In such cases,ColdFusion will call the custom tag twice—once when it encounters the start tag andagain when it encounters the end tag. ColdFusion creates an implicit ThisTag structurethat contains four variables to help the custom tag determine its context.Table 17.1shows the contents of the ThisTag structure.

Table 17.1 ThisTagVariable Contents

Key Value

AssocAttribs An array of attributes contained in associated nested tags.

ExecutionMode Indicates whether the tag has been called in reference to the starttag or end tag.Values are start or end.

GeneratedContent The evaluated form of all content that has been embedded within thestart and end tags.The custom tag can change this variable, affectingits own output.

HasEndTag A Boolean that indicates whether the tag has an associated end tag.This variable is most often used for sanity checking.A custom tag thatexpects both start and end tags should throw an error if the value ofHasEndTag is false.

Custom Tags that have both start and end tags should first check the ExecutionModevariable. If the value is start, the tag should check for mandatory and optional attrib-utes, initializing and undefined optional attributes. If the value of the variable is end, thecustom tag should implement the primary algorithm.

The biu.cfm custom tag represents a significant addition to the CFML language.The <cf_biu/> tag makes all embedded content bold, italicized, and underlined.Thecustom tag explicitly sets its GeneratedContent variable to implement this functional-ity.The expression <cfset ThisTag.GeneratedContent =“<b><i><u>#ThisTag.GeneratedContent#</u></i></b>”> wraps any contentcontained within the start and end tags with the HTML <b/>, <i/>, and <u/> tags.

23 0672324628 CH17 6/8/05 11:10 AM Page 233

Page 257: ColdFusion MX Developer's Cookbook (Developer's Library)

234 Chapter 17 ColdFusion Custom Tags

17.6. Building Nested TagsYou want to use nested custom tags for increased flexibility.

Techniquemailto.cfm:

<cfparam name=”Attributes.address”>

<cfassociate basetag=”cf_massmailer” dataCollection=”addresses”>

massmailer.cfm:

<cfparam name=”Attributes.from”>

<cfparam name=”Attributes.subject”>

<cfparam name=”Attributes.server”>

<!---

check for executionmode = ‘end’ in order to

make sure we execute the body of this tag *after*

processing all nested sub-tags

--->

<cfif ThisTag.executionmode is ‘end’>

<cfset addressarray = ArrayNew(1)>

<cfif isArray(ThisTag.addresses)>

<cfloop from=”1” to=”#ArrayLen(ThisTag.addresses)#” index=”i”>

<cfset attr = ThisTag.addresses[i]>

<cfset emailaddr = attr.address>

<cfset addressarray[i] = emailaddr>

</cfloop>

</cfif>

<cfmail to=”#ArrayToList(addressarray,” “)#”

from=”#Attributes.from#”

subject=”#Attributes.subject#”

server=”#Attributes.server#”>#ThisTag.GeneratedContent#</cfmail>

<cfset ThisTag.GeneratedContent = “”>

</cfif>

massmailerClient.cfm:

<cf_massmailer from=”[email protected]

subject=”test” server=”smtp.mydomain.com”>

<cf_mailto address=”[email protected]”>

<cf_mailto address=”[email protected]”>

<cf_mailto address=”[email protected]”>

<cf_mailto address=”[email protected]”>

<cf_mailto address=”[email protected]”>

23 0672324628 CH17 6/8/05 11:10 AM Page 234

Page 258: ColdFusion MX Developer's Cookbook (Developer's Library)

23517.7. Encoding Custom Tags

<cf_mailto address=”[email protected]”>

Message Text

</cf_massmailer>

CommentsNesting custom tags can be an elegant way to pass dynamic information.This approachis often more practical than specifying a long, unwieldy attribute list. ColdFusion imple-ments nested custom tags via the <cfassociate> CFML tag. <cfassociate> links achild tag’s attribute list to its parent tag. By default, the child tag’s attributes are placedinto the parent’s ThisTag.AssocAttribs array of structures. However, the child tagmay also specify to the parent attribute where its attributes should be placed.The mailto.cfm example uses the dataCollection attribute of the <cfassociate> tagto specify that its attribute lists are found in the variable ThisTag.addresses of theparent tag.

The examples shown in this section implement a custom tag called <cf_massmailer> that accepts one or more nested <cf_mailto> sub-tags.The intentof this example is to implement a wrapper for the <cfmail> tag (or any other mailengine) that is designed to send one email to a large recipient list. By standardizing onthis custom tag, you can radically change the implementation of the underlying messag-ing system without disturbing its call semantics.

The mailto.cfm template contains the implementation of the <cf_mailto> childtag.This tag is used to specify a single email address to which the email should be sent.The user can nest one or more of these tags within the <cf_massmailer> custom tag.The logic behind the <cf_mailto> tag is straightforward; it must only associate itsaddress attribute with the parent <cf_massmailer> tag.

The massmailerClient.cfm template shows how easy it is to use the <cf_massmailer> tag and its associated <cf_mailto> tag.The message text canappear anywhere within the <cf_massmailer> start and end tags.

17.7. Encoding Custom TagsYou want to encode your tag for distribution so that others cannot see itssource code.

TechniqueUse the cfencode.exe command to encrypt a custom tag.

c:\CFusionMX\bin\cfencode.exe biu.cfm biu_encoded.cfm /h

“Bold, Italicize, Underline” /v “2”

23 0672324628 CH17 6/8/05 11:10 AM Page 235

Page 259: ColdFusion MX Developer's Cookbook (Developer's Library)

236 Chapter 17 ColdFusion Custom Tags

CommentsYou may have purchased or downloaded a prepackaged custom tag from the ColdFusionDeveloper’s Exchange. If so, there is a pretty good chance that the tag you downloaded isencrypted so that its source cannot be copied or modified illegally.You might wish toencode your own custom tags for distribution in a similar manner. Fortunately,ColdFusion provides a utility that you can use to encrypt your own ColdFusion tem-plates.

The cfencode.exe program, included in the bin directory of your ColdFusion dis-tribution, is a command-line tool that reads a ColdFusion source file, encrypts it, andwrites it back to disk. Once encrypted, the ColdFusion template can be deployed andexecuted on any ColdFusion server, but it can no longer be modified.

This example uses the cfencode.exe utility to encrypt the biu.cfm custom tag.The command’s syntax is as follows:

cfencode.exe infile [outfile] [/r] [/q] [/h “header”] /v “2”

Table 17.2 provides a description of the command’s arguments.

Table 17.2 cfencode.exe Arguments

Argument Description

infile Mandatory. One or more source files to encode.

outfile Optional.The name of the new file(s) to be written. Can be left blank for in-place encoding.

/r Optional. Recursively process directories.

/q Optional. Suppress warning messages.

/h Optional. Include a custom header message in the encoded file./v Mandatory.The encryption version number to be used.

17.8. Using <cfmodule>You want to call a custom tag regardless of its location.

Technique<cfparam name=”name” default=”Elizabeth”>

<cfset attrs = StructNew()>

<cfset attrs.name = “Elizabeth”>

<cfmodule template=”./greetingTag.cfm” attributeCollection=”#attrs#”>

23 0672324628 CH17 6/8/05 11:10 AM Page 236

Page 260: ColdFusion MX Developer's Cookbook (Developer's Library)

23717.9. Using <cfimport>

CommentsThe <cfmodule> tag allows you to invoke a custom tag by explicitly stating the tem-plate to use.The tag requires you to specify the template attribute, which spells out arelative template path for the custom tag.Alternatively, you can use the tag’s name attrib-ute to provide a dot-delimited directory path to the custom tag template, relative to theColdFusion Custom Tags directory. For example, the command:

<cfmodule name=”com.mycompany.util.UtilTag”>

would execute the following template:

<ColdFusion Install Directory>/CustomTags/com/mycompany/util/UtilTag.cfm

Attributes can be passed to a custom tag called by <cfmodule> in one of two ways.Individual attributes can be named by using the attribute_<attribute name>naming convention. For example, the command:

<cfmodule template=”util.cfm” attribute_name=”Steve”

attribute_email=”[email protected]”>

would call the util.cfm template, passing in the attributes name and email.You can also use the attributeCollection attribute of the <cfmodule> tag tocommunicate a custom tag’s attributes.The same custom tag can be called with the fol-lowing statements:

<cfset attrs = StructNew()>

<cfset attrs.name = “Steve”>

<cfset attrs.email = “[email protected]”>

<cfmodule template=”util.cfm” attributeCollection=”#attrs#”>

The attributeCollection attribute will work with any custom tag that you call,even if you are calling the tag with the <cf_ prefix instead of with <cfmodule>.This isa useful technique when the attributes you want to set are not known until runtime.

17.9. Using <cfimport>You want to use the Java Server Pages prefix notation to access groups of JSPor ColdFusion custom tags.

Technique<cfparam name=”name” default=”Alex”>

<cfimport prefix=”utiltags” taglib=”taglib”>

<utiltags:greetingTag name=”#name#”>

23 0672324628 CH17 6/8/05 11:10 AM Page 237

Page 261: ColdFusion MX Developer's Cookbook (Developer's Library)

238 Chapter 17 ColdFusion Custom Tags

Comments<cfimport> is a new tag in ColdFusion MX that enables you to import CFMLCustom Tag directories or JSP Tag Libraries and call them with a JSP-like prefix nota-tion.The tag has one required attribute, taglib, which is a tag library URI.The URIcan be one of the following: a directory containing custom tags, a URL to a JAR file ina Web application, or a path to a JSP tag library descriptor (a .TLD file).The tag alsoaccepts an optional prefix attribute that assigns a prefix to the collection of tags inorder to distinguish them from other tag namespaces.

This example imports a directory called “taglib”.The directory contains some ofthe custom tag examples reviewed in this chapter.The example assigns the prefix utiltags to the custom tags found in the “taglib” directory.These tags can now becalled directly with a utiltags: prefix. For example, the template calls thegreetingTag custom tag with the following expression:

<utiltags:greetingTag name=”#name#”>

The big benefit to the <cfimport> tag is that it allows you to leverage any JSP taglibraries that are available to you. If you intend to import JSP tag libraries, you shouldgive serious thought to using the <cfimport> tag to import all of your ColdFusioncustom tags as well, because doing so gives your code a more consistent look.

23 0672324628 CH17 6/8/05 11:10 AM Page 238

Page 262: ColdFusion MX Developer's Cookbook (Developer's Library)

18CFX API Custom Tags

18.0. IntroductionCFX tags allow you to utilize APIs (Application Programming Interfaces) available toJava and C++ developers from within ColdFusion.The CFX API allows you to createyour own tags that are executed on the server by ColdFusion.

CFX tags can be written in either Java or C++; however, it’s optimal to use Javawhenever possible for several reasons.The first reason is that Java CFX tags don’t need tobe recompiled or rewritten for each operating system on which they are executed.WhenJava code is compiled, it is stored in a machine-independent format that can be executedon any machine that has a Java runtime environment installed (ColdFusion MX installs aJava Runtime Environment during its installation process).When C++ is compiled, onthe other hand, it is stored in a platform-specific format.

Also because ColdFusion MX is written in Java, it can execute a Java CFX tag withmuch less overhead than it can a C++ tag.

Although Java is the preferred language on ColdFusion MX, sometimes there aretasks that are much easier completed with C++ than with Java. For example, interactingwith the server operating system is often much easier with C++.

In the Enterprise version of ColdFusion MX, you can create JSP custom tag librariesto perform many of the tasks that Java CFX tags perform.With JSP tag libraries, you cancreate nested tags and tags that use the tag body content.The API for creating JSP taglibraries is more robust than the CFX API. If you do decide to use JSP custom tags, keepin mind that Java CFX tags can be used on ColdFusion 4.0 and up, whereas JSP tagsonly work on the Enterprise versions of ColdFusion MX. JSP custom tag libraries arecovered in Chapter 24,“J2EE Interoperability.”

This chapter examines four functionally different CFX API custom tags; each tag isimplemented in both Java and C++. Before reading this chapter, you might want toreview Java, C++, and object-oriented programming if you need to.

24 0672324628 CH18 6/8/05 11:10 AM Page 239

Page 263: ColdFusion MX Developer's Cookbook (Developer's Library)

240 Chapter 18 CFX API Custom Tags

18.1. Creating a Simple Java CFX TagYou want to create a ColdFusion custom tag using the Java programming language.

TechniqueImplement the com.allaire.cfx.CustomTag interface to create a CFX custom tag.Use the com.allaire.cfx.Response.write() method to print output to theresponse.

<b>Memory Status:</b><br>

<CFX_WriteMemoryStatus>

Here’s the CFX_WriteMemoryStatus.java file:import com.allaire.cfx.*;

public class CFX_WriteMemoryStatus

implements CustomTag

{

public void processRequest(Request request, Response response)

throws Exception

{

Runtime thisJVM = Runtime.getRuntime();

long freeMem = thisJVM.freeMemory();

freeMem /= 1024; //convert from bytes to KB

String strFreeMem = String.valueOf(freeMem); //convert to a string

//write the value to the response

response.write(strFreeMem);

response.write(“KB of free memory in the JVM.<br>”);

long totalMem = thisJVM.totalMemory();

totalMem /= 1024; //convert from bytes to KB

String strTotalMem = String.valueOf(totalMem); //convert to a string

response.write(strTotalMem);

response.write(“KB of memory total in the JVM.<br>”);

}

}

CommentsWhat is a Java CFX tag? The answer can be explained to any experienced Java developerwith one sentence:“any class that implements the com.allaire.cfx.CustomTag

24 0672324628 CH18 6/8/05 11:10 AM Page 240

Page 264: ColdFusion MX Developer's Cookbook (Developer's Library)

24118.2. Using Tag Attributes

interface.” Interfaces are a means to define a standard for the structure of a Java class; theyare essentially a list of methods that a class must define.When a class meets the standard,it is said to implement the interface.The interface itself contains no functional code, justthe method declarations.

For a class to implement the com.allaire.cfx.CustomTag interface, it must pro-vide a definition for a method with the following method prototype public voidprocessRequest(com.allaire.cfx.Request, com.allaire.cfx.Response)

throws java.lang.Exception.When ColdFusion executes the CFX tag, theprocessRequest method is called.

The processRequest method is passed two objects by ColdFusion—a requestobject and a response object.The request object contains methods to get informa-tion about the tag request (such as the tag attributes).The response object providesmethods to print messages or set variables.

In the CFX_WriteMemoryStatus tag, the write method prints strings containinginformation about the memory status to the HTTP response output stream.Table 18.1shows the methods of the Response interface.

To compile the Java file, use the javac compiler that comes with the JDK (JavaDeveloper’s Kit).When you compile the tag, the cfx.jar file (located in the lib direc-tory of your ColdFusion installation) must be in the classpath.This can be done byadding the JAR file to your classpath environment variable, or by adding the –class-path switch to javac. javac will create a .class file (section 9 of this chapter explainshow to register the CFX tag).

Table 18.1 The com.allaire.cfx.Response Interface

Method Meaning

void write(String value) Writes the string to the caller’s output stream.

void setVariable Sets a variable in the calling ColdFusion template.(String varName, String value) Seesection 3 of this chapter for more information.

Query addQuery Adds a query to the calling template with a (String name, String[] columns) specified name and specified columns. Returns a

reference to the Query. See section 4 of thischapter for more information.

void writeDebug(String val) Writes a string to the debug output stream.

18.2. Using Tag AttributesYou want to read input from the tag attributes inside the Java CFX tag.

TechniqueUse the attributeExists, getAttribute, and getIntAttribute methods of thecom.Allaire.cfx.Request object to read the tag attributes.

24 0672324628 CH18 6/8/05 11:10 AM Page 241

Page 265: ColdFusion MX Developer's Cookbook (Developer's Library)

242 Chapter 18 CFX API Custom Tags

<cfset str = “SubString”>

<CFX_SubString string=”#str#” start=”3”>

<CFX_SubString string=”#str#” start=”0” end=”3”>

Here’s the CFX_SubString.java file:

import com.allaire.cfx.*;

public class CFX_SubString

implements CustomTag

{

public void processRequest(Request request, Response response)

throws Exception

{

String theString;

int startPos;

if (!request.attributeExists(“STRING”)) {

throw new Exception(“Required attribute STRING is missing”);

}

if (!request.attributeExists(“START”)) {

throw new Exception(“Required attribute START is missing”);

}

theString = request.getAttribute(“STRING”);

startPos = request.getIntAttribute(“START”);

//END is an optional attribute

if (request.attributeExists(“END”)) {

theString = theString.substring(startPos,

request.getIntAttribute(“END”));

}

else {

theString = theString.substring(startPos);

}

response.write(theString);

}

}

CommentsThe CFX_SubString tag reads a string passed in through the string attribute andreturns a subset of the string that starts at the position specified by the start attribute.The substring then ends either at the end of the string or at the position specified by theend attribute.

24 0672324628 CH18 6/8/05 11:10 AM Page 242

Page 266: ColdFusion MX Developer's Cookbook (Developer's Library)

24318.2. Using Tag Attributes

Because this tag is useless without a string to operate on, the string attribute mustexist.You can determine whether an attribute was passed by using theattributeExists method of the request object.The attributeExists methodtakes in a string that represents the attribute name, and returns true or false dependingon whether the attribute does indeed exist.

To get the value passed into the attribute, you use the getAttribute method if youwant a string, or the getIntAttribute method if you want an integer. Both methodstake the name of the attribute for the first argument; getIntAttribute can also take adefault value if the attribute doesn’t exist or if the attribute can’t be converted to aninteger.

One big limitation of the getAttribute method is that it can return only strings.There is no way to pass a structure or array to a CFX tag without first serializing it toWDDX (See Chapter 21,“WDDX,” for more information about WDDX) or to anotherstring representation.

The attribute names passed into the getAttribute, getIntAttribute, orattributeExists methods are not case sensitive.Table 18.2 shows a listing of themethods in the Request interface.

Table 18.2 The com.allaire.cfx.Request Interface

Method Meaning

boolean attributeExists Determines whether a particular attribute was passed (String name) to the tag.

String getAttribute Returns the value of the specified attribute.(String name)

int getIntAttribute Returns the integer value of an attribute.You can (String name, int default) optionally specify a default value; used if the attribute

value does not exist or cannot be converted to an int.

Query getQuery() Returns a reference to the query passed in to theQUERY attribute of the tag.

String[] getAttributeList() Returns an array containing the names of all attributespassed into the tag.

boolean debug() Returns true if the attribute ““debug”” is present inthe tag.

NoteExceptions thrown from within the processRequest method are propagated to the calling CFML tem-

plate.

24 0672324628 CH18 6/8/05 11:10 AM Page 243

Page 267: ColdFusion MX Developer's Cookbook (Developer's Library)

18.3. Setting ColdFusion VariablesYou want to set a ColdFusion variable from within the Java CFX tag.

TechniqueUse the setVariable method in the response object to set a ColdFusion variablewithin a Java CFX tag.

<CFX_GetMemoryStatus variable=”memStruct”>

<cfdump var=”#memStruct#” label=”Memory Status”>

<!--- convert to mega bytes --->

<cfset freeMem = (memStruct.freeMemory / 1024) / 1024>

<cfoutput>#Round(freeMem)#MB of free Memory.</cfoutput>

Here’s the CFX_GetMemoryStatus.java file:

import com.allaire.cfx.*;

public class CFX_GetMemoryStatus

implements CustomTag

{

public void processRequest(Request request, Response response)

throws Exception

{

Runtime thisJVM = Runtime.getRuntime();

long freeMem = thisJVM.freeMemory();

String strFreeMem = String.valueOf(freeMem); //convert to a string

long totalMem = thisJVM.totalMemory();

String strTotalMem = String.valueOf(totalMem); //convert to a string

if (!request.attributeExists(“VARIABLE”)) {

throw new Exception(“Required attribute VARIABLE missing”);

}

String structName = request.getAttribute(“VARIABLE”);

response.setVariable(structName + “.freeMemory”, strFreeMem);

response.setVariable(structName + “.totalMemory”, strTotalMem);

}

}

244 Chapter 18 CFX API Custom Tags

24 0672324628 CH18 6/8/05 11:10 AM Page 244

Page 268: ColdFusion MX Developer's Cookbook (Developer's Library)

24518.4. Using Queries in Java CFX Tags

CommentsAlthough being able to write variables to the HTTP response is handy at times, it’s oftena better practice to set a variable and let the calling CFML template display or manipu-late it at will.The setVariable method allows you to do just that.

In the CFX_GetMemoryStatus tag, you use an attribute called variable to repre-sent the name of a structure that holds the memory variables that you set.

When you’re ready to set the variable, you use the setVariable method in theresponse object. setVariable takes two arguments, both of which must be strings.The first argument is the name of the variable and the second argument is the value ofthe variable.

NoteIn versions of ColdFusion prior to MX, variable names with a . (dot) were not structures, and there was no

way to create structures from a CFX tag.

18.4. Using Queries in Java CFX TagsYou want to read and create a query object from within your Java CFX tag.

TechniqueUse the getQuery method to get an input query, and use addQuery to create a newquery.

<CFX_ReverseQuery query=”#someQuery#” result=”reversedQuery”>

<cfdump var=”#reversedQuery#” label=”Reversed”>

Here’s the CFX_ReverseQuery.java file:

import com.allaire.cfx.*;

public class CFX_ReverseQuery

implements CustomTag

{

public void processRequest(Request request, Response response)

throws Exception

{

Query inputQuery = request.getQuery();

if (inputQuery == null) {

throw new Exception(“Required attribute QUERY missing.”);

}

if (!request.attributeExists(“RESULT”)) {

24 0672324628 CH18 6/8/05 11:10 AM Page 245

Page 269: ColdFusion MX Developer's Cookbook (Developer's Library)

246 Chapter 18 CFX API Custom Tags

throw new Exception(“Required attribute RESULT missing.”);

}

String resultQueryName = request.getAttribute(“RESULT”);

String[] columns = inputQuery.getColumns();

Query result = response.addQuery(resultQueryName, columns);

int rowCount = inputQuery.getRowCount();

//reverse the query

for(int r=rowCount;r>0;r--) {

int row = result.addRow();

for (int c=1;c<=columns.length;c++) {

String data = inputQuery.getData(r, c);

result.setData(row, c, data);

}

}

}

}

CommentsThe CFX_ReverseQuery tag is passed a query and returns a copy of the query inreverse order.

Queries in Java CFX tags are represented by the com.allaire.cfx.Query inter-face.The Query interface provides methods to modify and add data to the query.Thesemethods are listed in Table 18.3.

Table 18.3 The com.allaire.cfx.Query Interface

Method Meaning

int addRow() Adds a row to the query and returns theindex of the new row.

String[] getColumns() Returns an array of column names.

int getRowCount() Returns the number of rows in the query—the recordcount.

String getData(int row, int column) Gets the contents of a cell in the query spec-ified by a row index and column index.

void setData Sets the value of a cell specified by a row(int row, int column, String data) index and a column index.

String getName() Returns the name of the query.int getColumnIndex(String name) Returns the column index by column name.

24 0672324628 CH18 6/8/05 11:10 AM Page 246

Page 270: ColdFusion MX Developer's Cookbook (Developer's Library)

24718.5. A Simple C++ CFX Tag

CFX tags allow only one query to be passed to the tag; the query should be passed withthe query attribute.You can retrieve a reference to the query by calling the requestobject’s getQuery() method.

To add a new query to the calling CFML template, use the addQuery method in theresponse object. addQuery takes two arguments—the query name and an array ofcolumn names.A reference to the new query is returned from addQuery.

Once you have a reference to the query, you can find some information about it.Toget an array of columns, call the getColumns() method.The number of rows in thequery is returned by the getRowCount() method.With this information, you can loopthrough the query and copy the data in to the new query in reverse order.

To add a row to the query, call the addRow() method. It returns the index of therow that was added. Next, you copy the data to the new row, and then call thegetData() method to extract the contents in the original query object. By passinggetData() a row and a column, you’ll get a string representing the data in that cell.You then set the cell in the new query with the setData() method, which takes a row,a column, and a string.

18.5. A Simple C++ CFX TagYou want to create a simple CFX custom tag using the C++ programming language.

TechniqueWrite a ProcessRequest function that takes a pointer to a CCFXRequest object.

#include “stdafx.h” // Standard MFC libraries

#include “windows.h” // Windows Functions, GlobalMemoryStatus

#include “cfx.h” // CFX Custom Tag API

void ProcessTagRequest( CCFXRequest* pRequest )

{

try

{

CString buffer;

MEMORYSTATUS stat;

//get memory statistics

GlobalMemoryStatus(&stat);

//free physical memory

unsigned long freeMem = stat.dwAvailPhys;

freeMem /= 1024; //convert from bytes to KB

//convert long to string

ltoa(freeMem, buffer.GetBuffer(16), 10);

24 0672324628 CH18 6/8/05 11:10 AM Page 247

Page 271: ColdFusion MX Developer's Cookbook (Developer's Library)

248 Chapter 18 CFX API Custom Tags

pRequest->Write(buffer);

pRequest->Write(“KB of physical memory is free.<br>”);

//free physical memory

unsigned long totalMem = stat.dwTotalPhys;

totalMem /= 1024; //convert from bytes to KB

//convert long to string

ltoa(totalMem, buffer.GetBuffer(16), 10);

pRequest->Write(buffer);

pRequest->Write(“KB of physical memory total.<br>”);

}

// Catch Cold Fusion exceptions & re-raise them

catch( CCFXException* e )

{

pRequest->ReThrowException( e ) ;

}

// Catch ALL other exceptions and throw them as

// Cold Fusion exceptions (DO NOT REMOVE! --

// this prevents the server from crashing in

// case of an unexpected exception)

catch( ... )

{

pRequest->ThrowException(

“Error occurred in tag CFX_WRITEMEMORYSTATUS”,

“Unexpected error occurred while processing tag.” ) ;

}

}

CommentsThe easiest way to create a CFX tag in C++ is by using the project wizard in MicrosoftVisual C++.The wizard will set up the required compiler settings and create the neededfiles.

As mentioned in the introduction, C++ CFX tags on UNIX need to be recompiledon the platform on which they will run.To compile a tag for UNIX, look at the make-files included in the directory list CFX tag (found in the cfx directory of yourColdFusion installation). C++ code tends to be platform-specific.CFX_WriteMemoryStatus happens to only work on Windows because it is callingWindows-specific functions.The C++ implementation of CFX_GetMemoryStatus(discussed in section 7) uses the same functions and also will not work on UNIX.Theremaining C++ CFX tags should work on UNIX with very little modification.

24 0672324628 CH18 6/8/05 11:10 AM Page 248

Page 272: ColdFusion MX Developer's Cookbook (Developer's Library)

24918.5. A Simple C++ CFX Tag

All language differences aside, the API for creating C++ CFX tags is very similar tothe Java CFX tag API.The main difference is that there is no Response object, only aRequest object that has all the methods that the Response object does in the Java API.

A pointer to a CCFXRequest object is passed in to the ProcessTagRequest func-tion.With the pointer, you invoke the Write method to output to the HTTP response.

Notice that in the C++ implementation of the CFX_WriteMemoryStatus, you candetermine the total amount of physical memory, but the Java implementation reports theamount of memory in the JVM only.

You can use the CFML code from the technique discussed in section 1 to test theoutput of CFX_WriteMemoryStatus in the C++ implementation.The methods in the CCFXRequest class are outlined in Table 18.4.

Table 18.4 The CCFXRequest Abstract Class

Method Meaning

void Write(LPCSTR value) Writes the string to the caller’s output stream.

void SetVariable Sets a variable in the calling ColdFusion (LPCSTR varName, LPCSTR value) template.

CCFXQuery* AddQuery(LPCSTR Adds a query to the calling template with a name, CCFXStringSet* columns) specified name and specified columns.

Returns a pointer to the query.

void WriteDebug(LPCSTR val) Writes a string to the debug output stream.

BOOL AttributeExists(LPCSTR name) Determines whether an attribute was passedinto the tag.

LPCSTR GetAttribute(LPCSTR name) Returns the value of the specified attribute.

CCFXQuery* GetQuery() Returns a pointer to the query passed in tothe QUERY attribute of the tag.

CCFXStringSet* GetAttributeList() Returns a pointer to CCFXStringSetcontaining the names of all attributes passedinto the tag.

BOOL Debug() Returns true if the attribute “debug” is present in the tag.

void ThrowException(LPCSTR error, ) Throws a ColdFusion exception.LPCSTR diagnostics

void ReThrowException Re-throws a caught exception.( CCFXException* e)

CCFXStringSet* CreateStringSet() Allocates and returns a pointer to a string set;memory will be automatically cleaned up byColdFusion.

24 0672324628 CH18 6/8/05 11:10 AM Page 249

Page 273: ColdFusion MX Developer's Cookbook (Developer's Library)

250 Chapter 18 CFX API Custom Tags

18.6. Using Tag AttributesYou want to read input from the tag attributes inside the C++ CFX tag.

TechniqueUse the AttributeExists and GetAttribute methods on the CCFXRequestobject.

#include “stdafx.h” // Standard MFC libraries, remove on unix

#include “cfx.h” // CFX Custom Tag API

#include <string> // Use STL string for unix compatibility

void ProcessTagRequest( CCFXRequest* pRequest )

{

try

{

if (!pRequest->AttributeExists(“STRING”)) {

pRequest->ThrowException(“Error occurred in tag CFX_SUBSTRING”,

“Required attribute STRING missing” ) ;

}

if (!pRequest->AttributeExists(“START”)) {

pRequest->ThrowException(“Error occurred in tag CFX_SUBSTRING”,

“Required attribute START missing” ) ;

}

std::string str = pRequest->GetAttribute(“STRING”);

std::string strStart = pRequest->GetAttribute(“START”);

int iStart = atoi(strStart.c_str());

if (pRequest->AttributeExists(“END”)) {

std::string strEnd = pRequest->GetAttribute(“END”);

int iEnd = atoi(strEnd.c_str());

str = str.substr(iStart, iEnd);

}

else {

str = str.substr(iStart);

}

pRequest->Write(str.c_str());

}

// Catch Cold Fusion exceptions & re-raise them

catch( CCFXException* e )

{

24 0672324628 CH18 6/8/05 11:10 AM Page 250

Page 274: ColdFusion MX Developer's Cookbook (Developer's Library)

25118.7. Setting ColdFusion Variables

pRequest->ReThrowException( e ) ;

}

// Catch ALL other exceptions and throw them as

// Cold Fusion exceptions (DO NOT REMOVE! --

// this prevents the server from crashing in

// case of an unexpected exception)

catch( ... )

{

pRequest->ThrowException(

“Error occurred in tag CFX_SUBSTRING”,

“Unexpected error occurred while processing tag.” ) ;

}

}

CommentsThe AttributeExists method checks for the existence of attributes.TheGetAttribute method is used to return a LPCSTR (a pointer to a character array) rep-resentation of the attribute value.The C++ API does not have a GetIntAttributemethod like the Java API does, so you have to handle the string-to-integer conversionyourself.

This example uses the Standard Template Library (STL) string class to representstrings, because CString is part of the Microsoft Foundation Classes (MFC) and notvery UNIX-friendly. STL strings typically work well across different platforms.

18.7. Setting ColdFusion VariablesYou want to set a ColdFusion variable from within in the C++ CFX tag.

TechniqueUse the SetVariable method to set a ColdFusion variable.

#include “stdafx.h” // Standard MFC libraries

#include “cfx.h” // CFX Custom Tag API

#include “windows.h” // Windows Functions, GlobalMemoryStatus

void ProcessTagRequest( CCFXRequest* pRequest )

{

try

{

CString buffer;

MEMORYSTATUS stat;

24 0672324628 CH18 6/8/05 11:10 AM Page 251

Page 275: ColdFusion MX Developer's Cookbook (Developer's Library)

252 Chapter 18 CFX API Custom Tags

if (!pRequest->AttributeExists(“VARIABLE”)) {

pRequest->ThrowException(

“Error occurred in tag CFX_GETMEMORYSTATUS”,

“Required attribute VARIABLE missing.” ) ;

}

CString var = pRequest->GetAttribute(“VARIABLE”);

//get memory statistics

GlobalMemoryStatus(&stat);

//free physical memory

unsigned long freeMem = stat.dwAvailPhys;

//convert long to string

ltoa(freeMem, buffer.GetBuffer(16), 10);

pRequest->SetVariable(var + “.freeMemory”, buffer);

//total physical memory

unsigned long totalMem = stat.dwTotalPhys;

//convert long to string

ltoa(totalMem, buffer.GetBuffer(16), 10);

pRequest->SetVariable(var + “.totalMemory”, buffer);

//more windows specific memory info

unsigned long availablePageFile = stat.dwAvailPageFile;

ltoa(availablePageFile, buffer.GetBuffer(16), 10);

pRequest->SetVariable(var + “.availablePageFile”, buffer);

unsigned long availableVirtual = stat.dwAvailVirtual;

ltoa(availableVirtual, buffer.GetBuffer(16), 10);

pRequest->SetVariable(var + “.availableVirtual”, buffer);

unsigned long memoryLoad = stat.dwMemoryLoad;

ltoa(memoryLoad, buffer.GetBuffer(16), 10);

pRequest->SetVariable(var + “.memoryLoad”, buffer);

unsigned long totalPageFile = stat.dwTotalPageFile;

ltoa(totalPageFile, buffer.GetBuffer(16), 10);

pRequest->SetVariable(var + “.totalPageFile”, buffer);

unsigned long totalVirtual = stat.dwTotalVirtual;

ltoa(totalVirtual, buffer.GetBuffer(16), 10);

pRequest->SetVariable(var + “.totalVirtual”, buffer);

}

// Catch Cold Fusion exceptions & re-raise them

24 0672324628 CH18 6/8/05 11:10 AM Page 252

Page 276: ColdFusion MX Developer's Cookbook (Developer's Library)

25318.8. Using Queries in C++ CFX Tags

catch( CCFXException* e )

{

pRequest->ReThrowException( e ) ;

}

// Catch ALL other exceptions and throw them as

// Cold Fusion exceptions (DO NOT REMOVE! --

// this prevents the server from crashing in

// case of an unexpected exception)

catch( ... )

{

pRequest->ThrowException(

“Error occurred in tag CFX_GETMEMORYSTATUS”,

“Unexpected error occurred while processing tag.” ) ;

}

}

CommentsThe SetVariable method can be used to set a variable in the calling ColdFusionpage. It takes two arguments, both of type LPCSTR.The first argument is the variablename and the second is the value.

In the C++ implementation of CFX_GetMemoryStatus, you can get much moreinformation about the memory, including virtual memory and page file information.This is due to the close relationship between C++ and the operating system.

18.8. Using Queries in C++ CFX TagsYou want to read and create a Query object from within your C++ CFX tag.

TechniqueUse GetQuery and AddQuery to get a CCFXQuery object, and then retrieve, add, oredit information about the query with methods in the CCFXQuery object.

#include “stdafx.h” // Standard MFC libraries, remove for unix

#include “cfx.h” // CFX Custom Tag API

#include <string> // Use STL String for unix

void ProcessTagRequest( CCFXRequest* pRequest )

{

try

{

CCFXQuery * pInputQuery = pRequest->GetQuery();

if (pInputQuery == NULL) {

pRequest->ThrowException(

24 0672324628 CH18 6/8/05 11:10 AM Page 253

Page 277: ColdFusion MX Developer's Cookbook (Developer's Library)

254 Chapter 18 CFX API Custom Tags

“Error occurred in tag CFX_REVERSEQUERY”,

“Required attribute QUERY missing.” ) ;

}

if (!pRequest->AttributeExists(“RESULT”)) {

pRequest->ThrowException(

“Error occurred in tag CFX_REVERSEQUERY”,

“Required attribute RESULT missing.” ) ;

}

std::string strResult = pRequest->GetAttribute(“RESULT”);

CCFXStringSet * pColumns = pInputQuery->GetColumns();

int iColumns = pColumns->GetCount();

int iRows = pInputQuery->GetRowCount();

CCFXQuery * pResultQuery =

pRequest->AddQuery(strResult.c_str(), pColumns);

//reverse the query

for(int r=iRows;r>0;r--) {

int row = pResultQuery->AddRow();

for (int c=1;c<=iColumns;c++) {

std::string strData = pInputQuery->GetData(r, c);

pResultQuery->SetData(row, c, strData.c_str());

}

}

}

// Catch Cold Fusion exceptions & re-raise them

catch( CCFXException* e )

{

pRequest->ReThrowException( e ) ;

}

// Catch ALL other exceptions and throw them as

// Cold Fusion exceptions (DO NOT REMOVE! --

// this prevents the server from crashing in

// case of an unexpected exception)

catch( ... )

{

pRequest->ThrowException(

24 0672324628 CH18 6/8/05 11:10 AM Page 254

Page 278: ColdFusion MX Developer's Cookbook (Developer's Library)

25518.8. Using Queries in C++ CFX Tags

“Error occurred in tag CFX_REVERSEQUERY”,

“Unexpected error occurred while processing tag.” ) ;

}

}

CommentsA pointer to the query passed into the QUERY attribute of the tag is retrieved by theGetQuery method. If a query is not passed to the tag, GetQuery will return NULL; oth-erwise, it returns a pointer to a CCFXQuery object.The methods of the CCFXQueryabstract class are explained in Table 18.5.

One difference between the CCFXQuery abstract class and the com.allaire.cfx.Query interface (in Java) is the GetColumns method. In Java, getColumns returns anarray of strings; in C++, it returns a pointer to a CCFXStringSet object.TheCCFXStringSet abstract class is similar to a list in ColdFusion.

Table 18.5 The CCFXQuery Abstract Class

Method Meaning

int AddRow() Adds a row to the query and returns the index of theadded row.

CCFXStringSet* GetColumns() Returns a pointer to a collection of column names.

int GetRowCount() Returns the number of rows in the query; therecordcount.

LPCSTR GetData Gets the contents of a cell in the query specified by(int row, int column) a row index and column index.

void SetData(int row, int Sets the value of a cell specified by a row index andcolumn, LPCSTR data) a column index.

LPCSTR getName() Returns the name of the query.int getColumnIndex Gets the column index by column name.(LPCSTR name)

24 0672324628 CH18 6/8/05 11:10 AM Page 255

Page 279: ColdFusion MX Developer's Cookbook (Developer's Library)

256 Chapter 18 CFX API Custom Tags

18.9. Installing a Java CFX TagYou want to register a Java CFX tag with ColdFusion.

TechniqueUse ColdFusion administrator’s “CFX Tags” link to register CFX tags. Java classes mustbe in the classpath.

CommentsSo now that you have written a CFX tag, you would like to use it in your ColdFusionapplication, or at least test it to see if it’s working. In order to use a CFX tag in CFML,the ColdFusion server needs to know where your compiled code resides and whichpiece of code contains the CFX tag.

The process for registering CFX tags is slightly different for C++ and Java tags.Thissection looks at each—both boil down to mapping a tag name to a procedure or class.

In order for ColdFusion to execute your compiled class file, the class file must be inthe classpath.The classpath is not actually a feature of ColdFusion, but rather a feature ofthe Java Virtual Machine.When the Java Virtual Machine is started, it is given a list ofdirectories and JAR files (the classpath).When the JVM has a request to instantiate anew class, it searches the directories and JAR files in the list to find the .CLASS file cor-responding to the class name.

The first step to installing a Java CFX tag is adding your CFX class file in your class-path.The directory <coldfusionroot>/wwwroot/WEB-INF/classes is already partof ColdFusion’s classpath.You can add additional directories or JAR files to the classpathin ColdFusion Administrator with the “Java and JVM” link.

Be sure not to put your class files in subdirectories under your classpath. Java treatsdirectories as package names, so if you put MyCFX.class in a subdirectory called cfx,Java can only access the class by the name cfx.MyCFX, and MyCFX must be compiledwith package cfx; as the first line in the code.

NoteThe classpath setting in the ColdFusion MX Administrator only allows a classpath of a limited number of

characters. You can manually edit your classpath by editing the java.class.path property in the

<coldfusionroot>/runtime/bin/jvm.config file.

Once the JVM can find your class, you have to let ColdFusion know what tag name youwant to map to your class.To do this, click the “CFX Tags” link in ColdFusionAdministrator, and then click the Register Java CFX button. Simply enter a tag name(CFX_MyTag) and a class name (MyCFX). Class names are case sensitive, but tag names arenot.You can optionally enter a description of the tag.The page for registering CFX tagsis shown in Figure 18.1.

24 0672324628 CH18 6/8/05 11:10 AM Page 256

Page 280: ColdFusion MX Developer's Cookbook (Developer's Library)

Figure 18.1 Registering a Java CFX tag.

18.10. Installing a C++ CFX TagYou want to register a C++ CFX tag with ColdFusion.

TechniqueUse ColdFusion administrator’s “CFX Tags” link to register CFX tags.

CommentsRegistering C++ CFX tags is actually a little bit easier than registering Java CFX tagsbecause you don’t have to worry about classpaths or packages; you simply point to aDLL (on Windows) or so (on UNIX) file.

In the ColdFusion Administrator, click “CFX Tags” and then click the Register C++CFX button. Enter the tag name (CFX_MyTag) and the path to the DLL or the file(c:\cfx\MyTag.dll).

Although the ColdFusion Administrator allows you to name your procedure some-thing other than ProcessTagRequest, you should stick to the standard.

25718.10. Installing a C++ CFX Tag

24 0672324628 CH18 6/8/05 11:10 AM Page 257

Page 281: ColdFusion MX Developer's Cookbook (Developer's Library)

258 Chapter 18 CFX API Custom Tags

The next option is the Keep Library Loaded check box.When this setting is checked,your CFX code will be retained in RAM, allowing for fast access. Chances are your pro-cedure won’t take up much RAM, so you should keep this option checked.

Finally, you can optionally enter a description of the CFX tag.The form for adding aC++ CFX tag is shown in Figure 18.2.

Figure 18.2 Registering a C++ CFX tag.

24 0672324628 CH18 6/8/05 11:10 AM Page 258

Page 282: ColdFusion MX Developer's Cookbook (Developer's Library)

19Components

19.0. IntroductionColdFusion components, new in ColdFusion MX, enable developers to create object-likestructures in ColdFusion. ColdFusion components, or CFCs, add many of the benefits ofobject-oriented programming in ColdFusion, without requiring you to learn much newCFML syntax.

Some of the benefits of using object-oriented programming include code reuse, aflexible and extensible design, and simplified maintenance. ColdFusion components alsohave these benefits.

ColdFusion components can also be easily used as Web services, thus allowing a highlevel of interoperability between several platforms.This is covered in Chapter 23,“WebServices.”

ColdFusion components rely heavily on the <cffunction> tag, which is covered inChapter 16,“User-Defined Functions.” It would be worthwhile to review the syntax of<cffunction> before delving into this chapter.

19.1. Defining a ComponentYou want to create a new ColdFusion component (a CFC).

TechniqueUse the <cfcomponent> tags with the <cffunction> tags to create a CFC.

Here is the component light.cfc:

<cfcomponent>

<cfset lightIsOn = false>

<cffunction name=”switch” returntype=”void”>

25 0672324628 CH19 6/8/05 11:10 AM Page 259

Page 283: ColdFusion MX Developer's Cookbook (Developer's Library)

260 Chapter 19 Components

<!--- if light is on turn it off, if off turn it on --->

<cfset lightIsOn = NOT lightIsOn>

</cffunction>

<cffunction name=”isLightOn” returntype=”boolean”>

<cfreturn lightIsOn>

</cffunction>

</cfcomponent>

CommentsBefore you get too far into the syntax, it’s important to examine some aspects of object-oriented programming, and understand how it relates to ColdFusion components.Thebest way to think about objects is to consider a physical object, for instance, a light.Alight can be on or off (its property is to emit light).There also needs to be a way to turnthe light on and off, a light switch—speaking programmatically, the switch is a functionyou can call. In object-oriented programming, you can bundle all of the functions andproperties (variables) of an object into an entity.

Once you’ve defined the structure of your light, in order to use it you have to instan-tiate it, or create an instance of it.You can create multiple light objects by using just onedefinition. Each light instance has its own storage for variables, so each instance can be atits own state.

The Light component is created in its own file with the extension .CFC(light.cfc).

The <cfcomponent> tags act as containers for defining the component. Local vari-ables defined within the <cfcomponent> tags (such as lightIsOn) are accessible onlyto functions within the component; they are sometimes referred to as instance variables(because each instance of a component can have a different value stored in the variable).

ColdFusion components don’t provide all of the features that most object-orientedlanguages provide. However, you can easily apply object-oriented design principles andpatterns when designing ColdFusion components.This is why studying object-orienteddesign is a worthwhile task for ColdFusion developers.

NoteYou can create variables that are accessible outside of the component by using a scope such as

application or session. You can also use a special scope called this inside a CFC to make the

variable accessible (for example, componentInstance.variableName). This practice might not

always lead to the best design.

The fact that only functions within the component can access the local variables is agood thing.You can validate the values to ensure, for example, that a number is alwaysabove zero.Additionally, you can have instance variables that developers calling your

25 0672324628 CH19 6/8/05 11:10 AM Page 260

Page 284: ColdFusion MX Developer's Cookbook (Developer's Library)

26119.1. Defining a Component

component cannot access.This concept is often called encapsulation, or data hiding.Encapsulation allows you to change code within the object without changing the codeused to call functions on the object. For example, consider light.cfc again, now witha light bulb that dies after a few uses:

<cfcomponent>

<cfset switchIsOn = false>

<cfset lightBulbIsGood = true>

<cfset counter = 0>

<cffunction name=”switch” returntype=”void”>

<cfset counter = counter + 1>

<cfif counter GT 3>

<cfset lightBulbIsGood = false>

</cfif>

<cfset switchIsOn = NOT switchIsOn>

</cffunction>

<cffunction name=”isLightOn” returntype=”boolean”>

<cfreturn switchIsOn AND lightBulbIsGood>

</cffunction>

</cfcomponent>

This is an example whereby the internal logic changed, but the external structureremained the same, making it very easy to deploy changes to the internal logic.

The <cfcomponent> tag has some optional attributes—hint and displayname—that can be used to describe your component.The hint attribute provides a hint as towhat the component does, and the displayname attribute is used to give the compo-nent a friendly name (you can use spaces).These attributes are used by the CFC explor-er, the GetMetaData function, and <cfdump>.The GetMetaData function is coveredlater in section 19.6.The CFC explorer displays the structure of your component in anHTML format.The CFC explorer is invoked by simply entering the URL of the CFCin your Web browser. For security reasons, you might be asked for your RDS orColdFusion administrator username and password before you can view the component.

The <cffunction> tag also has the hint and displayname attributes.Theseattributes have the same meaning in this context, and show up in the meta data.

NoteUsing the hint and displayname attributes in <cfcomponent> and <cffunction> can greatly

improve the readability of your code. These attributes also generate useful documentation when compo-

nents are viewed through the CFC Explorer. For these reasons, it is highly recommended that you take

advantage of these optional attributes.

25 0672324628 CH19 6/8/05 11:10 AM Page 261

Page 285: ColdFusion MX Developer's Cookbook (Developer's Library)

262 Chapter 19 Components

19.2 Instantiating a ComponentYou want to create an instance of a CFC.

TechniqueUse CreateObject or the <cfobject> tag to create an instance of a CFC.

<cfobject component=”Light” name=”lightInstance”>

OR

<cfset lightInstance = CreateObject(“component”, “Light”)>

CommentsThere are two ways to create an instance of a CFC—with the <cfobject> tag or withthe CreateObject function. CreateObject and <cfobject> are both functionallyequivalent.The only difference is that CreateObject can be used from within the<cfscript> tag.

The component attribute of <cfobject> tag takes the name of the CFC (the file-name minus .CFC).The name attribute is the name of the variable that holds a referenceto the CFC.With a reference to the CFC, you can invoke functions on it.

To instantiate a component with the CreateObject function, you pass in the string“component” as the type of object in the first argument (you can use CreateObjectand <cfobject> to create several types of objects such as Java, COM, and CORBA). Inthe second attribute, name, you pass the name of the CFC.

The technique in this section uses the light.cfc file created in the previous tech-nique.The code in this technique should reside in the same directory as the light.cfcfile.You can call CFCs that are stored in other directories, but doing so requires a slightlydifferent technique (see section 19.5 of this chapter for an explanation).

Once you have a component instance, you can pass the instance to different functionsor CFCs.You can also store a reference to a CFC instance in several scopes.

The following example uses an application scoped variable to allow the CFC topersist between page requests.When a user clicks the Click Switch button, the switchmethod is invoked on the light component (method invocation is covered in the nextsection).

<cfif NOT IsDefined(“application.light”)>

<cfset application.light =

CreateObject(“component”, “Light”)>

</cfif>

<cfif IsDefined(“form.switch”)>

<cfset application.light.switch()>

</cfif>

25 0672324628 CH19 6/8/05 11:10 AM Page 262

Page 286: ColdFusion MX Developer's Cookbook (Developer's Library)

<cfoutput>

The light is currently:

<cfif application.light.isLightOn()>

On

<cfelse>

Off

</cfif>

</cfoutput>

<form method=”post”>

<input type=”submit” name=”switch” value=”Click Switch”>

</form>

19.3. Invoking a Component MethodYou want to invoke methods on a CFC.

TechniqueUse dot notation or the <cfinvoke> tag to call a method on a CFC.

<cfobject component=”Counter” name=”counterInstance”>

<cfoutput>

#counterInstance.increment()#<br>

#counterInstance.increment()#<br>

</cfoutput>

<cfinvoke component=”#counterInstance#”

method=”increment”

returnvariable=”result”>

<cfoutput>#result#<br></cfoutput>

<!--- creates a new instance --->

<cfinvoke component=”Counter” method=”increment” returnvariable=”result”>

<cfoutput>#result#<br></cfoutput>

Here’s counter.cfc:<cfcomponent>

<cfset theCounter = 0>

<cffunction name=”increment” returntype=”numeric”>

<cfset theCounter = theCounter + 1>

<cfreturn theCounter>

</cffunction>

</cfcomponent>

26319.3. Invoking a Component Method

25 0672324628 CH19 6/8/05 11:10 AM Page 263

Page 287: ColdFusion MX Developer's Cookbook (Developer's Library)

264 Chapter 19 Components

CommentsThere are four ways to invoke a method (functions in an object are often called methods)in a CFC.The first way requires an instance of a CFC, the other three ways involveusing an instance or creating a new instance.

The first approach for invoking a method is using dot notation on an instance of aCFC.You use the syntax cfcInstanceName.methodName(arguments).The advan-tages to this approach are that it takes the least amount of code and works within<cfscript> tags.

The next two approaches use the <cfinvoke> tag to invoke the method. Dependingon whether you pass in CFC instance or a component name to the componentattribute of the <cfinvoke> tag, the result can be different. If you pass in a CFCinstance, the values stored in the instance variables (theCounter in this example) areretained. If you pass in a component name to the component attribute, a new instanceof the CFC is created.When a new instance of a CFC is created, the instance variabletheCounter is reset to zero.The output of the code in this technique is as follows:

1

2

3

1

Notice that the last line is reset to one, because you created a new instance of the com-ponent.

If a component method has arguments that must be passed, there are two ways toachieve this with <cfinvoke>.The first way is to simply pass attributes with the samename as the arguments in to the <cfinvoke> tag. For example:

<cfinvoke component=”Math” method=”divide” numerator=”5” denominator=”10”>

The second way to pass arguments to a component method involves a child tag of <cfinvoke> called <cfinvokeargument>.The <cfinvokeargument> tag has twoattributes; name and value.The name attribute is used to identify the name of theargument, and the value attribute is used to pass the variable value to the function.

<cfinvoke component=”Math” method=”divide”>

<cfinvokeargument name=”numerator” value=”5”>

<cfinvokeargument name=”denominator” value=”10”>

</cfinvoke>

Another way to pass arguments in to the <cfinvoke> tag is to create a structure ofarguments and then pass the structure in to the argumentcollection attribute.Thisfourth technique is shown here.

<cfset args = StructNew()>

<cfset args.numerator = 5>

<cfset args.denominator = 10>

<cfinvoke component=”Math” method=”divide” argumentcollection=”#args#”>

25 0672324628 CH19 6/8/05 11:10 AM Page 264

Page 288: ColdFusion MX Developer's Cookbook (Developer's Library)

26519.4. Component Inheritance

19.4. Component InheritanceYou want to create a new component that extends the functionality of anexisting component.

TechniqueUse the extends attribute of the <cfcomponent> tag to create a component thatinherits functionality from another component.

<cfobject component=”Manager” name=”bob”>

<cfobject component=”Employee” name=”fred”>

<cfset fred.init(1, “Fred”, “[email protected]”)>

<cfset bob.init(2, “Bob”, “[email protected]”, “1”)>

<cfoutput>

Fred’s Email: #fred.getEmail()#<br>

Bob’s Email: #bob.getEmail()#<br>

Is Bob Fred’s Manager? #YesNoFormat( bob.manages( fred.getEmployeeID() ) )#

</cfoutput>

Here’s employee.cfc:

<cfcomponent>

<cfset employeeID = 0>

<cfset name = “”>

<cfset email = “”>

<cffunction name=”init” returntype=”void”>

<cfargument name=”empID” type=”numeric” required=”true”>

<cfargument name=”empName” type=”string” required=”true”>

<cfargument name=”empEmail” type=”string” required=”true”>

<cfset employeeID = arguments.empID>

<cfset name = arguments.empName>

<cfset email = arguments.empEmail>

</cffunction>

<cffunction name=”getEmployeeID” returntype=”numeric”>

<cfreturn employeeID>

</cffunction>

<cffunction name=”getName” returntype=”string”>

<cfreturn name>

</cffunction>

<cffunction name=”getEmail” returntype=”string”>

<cfreturn email>

25 0672324628 CH19 6/8/05 11:10 AM Page 265

Page 289: ColdFusion MX Developer's Cookbook (Developer's Library)

266 Chapter 19 Components

</cffunction>

</cfcomponent>

Here’s manager.cfc:

<cfcomponent extends=”Employee”>

<!--- a list of employee id’s the manager manages --->

<cfset manageList = “”>

<cffunction name=”init” returntype=”void”>

<cfargument name=”empID” type=”numeric” required=”true”>

<cfargument name=”empName” type=”string” required=”true”>

<cfargument name=”empEmail” type=”string” required=”true”>

<cfargument name=”empList” type=”string” required=”false”>

<cfset employeeID = arguments.empID>

<cfset name = arguments.empName>

<cfset email = arguments.empEmail>

<cfset manageList = arguments.empList>

</cffunction>

<cffunction name=”manages” returntype=”boolean”>

<cfargument name=”empID” required=”true” type=”numeric”>

<cfreturn ListFind(manageList, arguments.empID)>

</cffunction>

</cfcomponent>

CommentsObjects that have an “is a” relationship (a tree is a plant) are prime candidates for inheri-tance.This technique uses the example: a Manager is an Employee.The Manager pos-sesses all of the properties that a regular Employee does, but also has a list of employeesthat he or she manages as an additional property.

The Manager CFC does not need to redefine the getEmployeeID, getName, orgetEmail functions; these function definitions are inherited from the Employee CFC.This is facilitated by adding extends=”Employee” to the <cfcomponent> tag in theManager CFC. Using inheritance often reduces the amount of code you need to write,because you can inherit code from other components.

Because inheritance usually saves you quite a bit of code, it is tempting to use inheri-tance on relationships that don’t make sense. For instance, you might try to inherit Catfrom Dog because they both have four legs. Don’t use inheritance unless you can say“object A is an object B.”

You may have noticed that the example defined the init function in both theEmployee and Manager CFCs.The implementation of the init function in theManager CFC is said to “override” that of the Employee CFC.The Manager CFCincludes an argument for the list of employees that the manager manages.

25 0672324628 CH19 6/8/05 11:10 AM Page 266

Page 290: ColdFusion MX Developer's Cookbook (Developer's Library)

Another tempting practice with inheritance is to use multiple inheritance; that is objectA inherits from object B and object C, but objects B and C do not inherit from eachother. Multiple inheritance exists in some languages such as C++, but is not allowed inColdFusion or Java.

You can, however, inherit from multiple components one at a time. For example,object A inherits from object B, which inherits from object C. In fact, by default, allcomponents inherit from a component named WEB-INF.cftags.component, whichis the base of all components.

One of the advantages of inheritance is that it allows developers to create APIs andframeworks that can be extended by other developers.The extended components thenwork seamlessly with the APIs.After all, when you use inheritance, your extended com-ponent is a form of its parent component. In other words, you can write a function thatexpects to receive an Employee and pass it a Manager.The function can also handleany component that inherits from Employee.This phenomenon is known as polymor-phism in object-oriented programming circles.

NoteBecause ColdFusion components support function overriding, but do not support function overloading (mul-

tiple function definitions with different arguments), it’s possible to override a function and change the

arguments so that the child class breaks polymorphic code. The init function in the Manager CFC adds

an argument, but because it designates the argument as not required, the function is still safe.

19.5. Accessing a ComponentYou want to access CFCs from multiple directories.

Technique<cfobject component=”cfcookbook.19.Light” name=”light”>

<cfoutput>#light.isLightOn()#</cfoutput>

CommentsIf you try to run a component in a directory other than the one it was defined in, youwill find that a NoSuchTemplateException is thrown. Components can be accessedfrom any ColdFusion template on your server as long as you fully qualify the compo-nent name.

The code in this technique instantiates a component namedcfcookbook.19.light.When ColdFusion is given this component name, it looksunder the Web root for the following file /cfcookbook/19/light.cfc. ColdFusionbarrows some naming conventions here from Java; the directory /cfcookbook/19/

26719.5. Accessing a Component

25 0672324628 CH19 6/8/05 11:10 AM Page 267

Page 291: ColdFusion MX Developer's Cookbook (Developer's Library)

268 Chapter 19 Components

translates to a package named cfcookbook.19. Each directory under the Web root is itsown package.

ColdFusion components also allow you to enable access to functions with theaccess attribute of the <cffunction> tag. Functions defined within a componentwith the attribute access=”package” can only be accessed by CFCs or templates inthe same package (directory). In addition, you can use access=”private” to writeconvenience functions that are available only to the CFC that defined them.

19.6. Using Component Meta DataYou want to retrieve information about a component’s methods and properties.

TechniquePass a component reference into the GetMetaData function and manipulate the result-ing structure.

<cfobject component=”Light” name=”light”>

<cfset metaData = GetMetaData(light)>

<cfdump var=”#metaData#” label=”MetaData For Light CFC”>

CommentsThe GetMetaData function can be useful for debugging or for building applicationsthat dynamically choose which methods to execute on a CFC by using the meta data.This process is often referred to as introspection.

GetMetaData takes one argument, a reference to a component.You can obtain a ref-erence to a component by using one of the methods mentioned in section 19.2 of thischapter, or by using the this keyword inside a CFC.The this keyword is a referenceto the current component instance (it is also a scope that can be used to make publicvariables).

The GetMetaData function, at a minimum, returns a structure with the followingkeys: extends, functions, name, path, and type.The name key stores the name ofthe CFC.The path key stores the path to the CFC on your server, and the type keyshould be set to component.

The extends key contains the meta data for the base component.All componentsintrinsically inherit from WEB-INF.cftags.component. If you used the extendsattribute to inherit from another component, it will appear in the extends key of thestructure.

In the functions key of the meta data structure is an array of structures, each struc-ture has information about a function in the component.The function structure mini-

25 0672324628 CH19 6/8/05 11:10 AM Page 268

Page 292: ColdFusion MX Developer's Cookbook (Developer's Library)

26919.6. Using Component Meta Data

mally has the keys name and parameters.The name key corresponds to the name ofthe function, and the parameters key holds an array of structures for each functionargument.The parameters structure has keys equivalent to the possible attributes forthe <cfargument> tag (name, returntype, default, and type).The structure in thefunctions array can also contain some additional keys depending the attributes presentin the <cffunction> tag, including access, displayname, hint, roles, andreturntype.

The best way to work with meta data is to output the meta data structure with<cfdump> and then extract the pieces you need. Keep in mind that the presence ofstructure keys depends on which attributes were used with the <cfcomponent>,<cffunction>, and <cfargument> tags.

25 0672324628 CH19 6/8/05 11:10 AM Page 269

Page 293: ColdFusion MX Developer's Cookbook (Developer's Library)

25 0672324628 CH19 6/8/05 11:10 AM Page 270

Page 294: ColdFusion MX Developer's Cookbook (Developer's Library)

20Objects

20.0. IntroductionColdFusion’s object support is perhaps one of the most underused features ofColdFusion. Using the <cfobject> tag, or its equivalent function CreateObject,allows you to have direct interaction with ColdFusion Components,Web services, Java,COM, or CORBA objects. Because ColdFusion Components (or CFCs) are imple-mented in the CFML language, an entire chapter is devoted to them (Chapter 19,“Components”).Web services are also covered in a separate chapter (Chapter 23,“WebServices”).This chapter covers the processes of creating and invoking Java, COM, andCORBA objects.

Using objects liberates your ColdFusion code from performing complex businesslogic.The logic is instead written and optimized in a separate class.

Using objects also can increase the performance and scalability of an application. Forexample, if the object can be distributed across multiple servers, you increase scalability.

Several third-party objects and components are available that can reduce the amountof time needed to develop an application. In addition, most third-party objects undergomore testing than you would normally administer, providing better reliability and stability.

20.1. Creating a Java Object InstanceYou want to create an instance of a Java object within ColdFusion.

TechniqueUse the <cfobject> tag or the CreateObject function to create an instance of a Javaobject:

<cfobject name=”stack” class=”java.util.Stack” type=”java” action=”create”>

26 0672324628 CH20 6/8/05 11:10 AM Page 271

Page 295: ColdFusion MX Developer's Cookbook (Developer's Library)

272 Chapter 20 Objects

or

<cfset stack = CreateObject(“java”, “java.util.Stack”)>

CommentsThere are two ways to create an instance of any arbitrary Java object in ColdFusion—<cfobject> and CreateObject. In the <cfobject> tag, four attributes are requiredto instantiate the object—name, class, type, and action.

The value of the name attribute corresponds to the name of the ColdFusion variablethat holds a reference to the instantiated Java object. Using one of the persistent scopes(application, session, server, or client) allows the object instance to persistbetween multiple page requests.

The class attribute of the <cfobject> tag defines the name of the Java class to beinstantiated.The class must be in the server’s classpath in order for ColdFusion to findthe code for the class. Several classes and packages are available natively as part of Java.Such classes can be instantiated without concern as to whether they have been added tothe classpath, as they are intrinsically part of the Java platform. Some of the most usefulclasses that are part of the Java platform can be found in the java.util package.Thejava.util package contains several data structures such as List, Hash Table, Set,Tree,and a Stack (this technique instantiates a Stack object).

Because the <cfobject> tag can also be used to instantiate ColdFusionComponents,Web services, CORBA, and COM objects, the type attribute is required.The action attribute is also required.To create an instance of a Java object, settype=”java” and action=”create”.Table 20.1 lists all of the attributes of the<cfobject> tag.

Table 20.1 <cfobject> Attributes

Attribute Type Meaning

type Java, CORBA, and COM The type of object to create: Java, CORBA, or COM.Required if the component attribute is not present.

name Java, CORBA, COM, The name of a variable that will hold a reference to Component,Web Service the object instance. Required.

class Java, CORBA, and COM An identifier to the class to be instantiated.Required if the component attribute is not present.

action Java, CORBA, and COM Java and CORBA always use the value create.With COM you can specify create or connect.Connect is used to connect to an existing object.Required if the component attribute is not present.

26 0672324628 CH20 6/8/05 11:10 AM Page 272

Page 296: ColdFusion MX Developer's Cookbook (Developer's Library)

27320.2. Invoking Methods on an Object

context CORBA and COM Specifies the context in which the object will becreated. Possible values in CORBA are IOR ornameservice.When type=”COM” is used, thevalues are InProc, local, or remote. Requiredfor CORBA; COM objects use registry settings asa default.

server COM only A DNS or UNC path. Required ifcontext=”remote”.

locale CORBA only The name of the CORBA ORB connection to use.Required if there are more than one registeredconnectors in the ColdFusion Administrator.

component Component’s only The name of a ColdFusion Component to createan instance of. See Chapter 19 for more informa-tion.

webservice Web Service’s only A URL to a WSDL file, which describes the service.

The CreateObject function can also be used to instantiate a Java object with slightlyless code.The first argument of the CreateObject function corresponds to the typeattribute in <cfobject>.The second argument represents the name of the Java class toinstantiate (corresponds to the class attribute of <cfobject>). CreateObjectreturns a reference to an instance to the Java object.This reference can then be stored ina ColdFusion variable.

Although CreateObject and <cfobject> yield the same result, CreateObjectcan be used within <cfscript> blocks, and can be invoked with less code.

20.2. Invoking Methods on an ObjectYou want to invoke static or instance methods on an existing object.

TechniqueUse the syntax instanceName.methodName(arguments) to invoke a method on anobject.

<cfset stack = CreateObject(“java”, “java.util.Stack”)>

<cfset stack.push(“A”)>

<cfset stack.push(“B”)>

<cfoutput>

pop: #stack.pop()#<br>

pop: #stack.pop()#<br>

</cfoutput>

Table 20.1 Continued

Attribute Type Meaning

26 0672324628 CH20 6/8/05 11:10 AM Page 273

Page 297: ColdFusion MX Developer's Cookbook (Developer's Library)

CommentsThe technique to invoke a method on an object is identical for each type of object thatColdFusion supports (Components, Java, CORBA, COM, and Web services).

This technique invokes a method on a Java instance—namely methods on thejava.util.Stack class.The stack data structure allows you to push objects onto thestack, and then pop them off the top.The first item on the stack will be the last itempopped off (this is known formally as Last In First Out, or LIFO).

Items are placed on the stack with the push method.The push method takes oneargument of type java.lang.Object. Because all methods in Java inherit fromjava.lang.Object, any variable in ColdFusion MX also inherits fromjava.lang.Object behind the scenes.Thus you can pass any variable into the pushmethod; however, this technique used the literal strings “A” and “B” for simplicity.

Items are popped off the top of the stack with a call to the pop method. Execution ofthis technique outputs “B” “A” (LIFO ordering).

You can also invoke static methods (methods that do not use instance variables) withColdFusion MX. However, in ColdFusion you must still create an instance of the objectbefore you can call a method on it, which defeats the performance benefits of using stat-ic methods.The code to invoke a static method is the equivalent to an instance method.

<cfset system = CreateObject(“java”, “java.lang.System”)>

<cfoutput>#system.currentTimeMillis()#</cfoutput>

Because ColdFusion MX is a loosely typed language, all numbers are represented asstrings.When a ColdFusion number is passed to a Java method that expects an int as anargument, ColdFusion will convert the string representation of the number into an inte-ger.These conversions will degrade performance. If you need to perform several Javamethod invocations, especially those using data types other than String, you might bebetter off writing a high-level wrapper class in Java.

If a Java method is overloaded (it can be passed different data types), you may need touse the JavaCast function to explicitly cast a ColdFusion variable to a primitive datatype.The JavaCast function takes two arguments; the first argument is the type to castto. Possible values for this argument include int, string, boolean, long, anddouble.The second argument of the JavaCast function is the value you are casting.

<cfset x =

someObject.overloadedMethod(JavaCast(“int”, “5”))>

<cfset y =

someObject.overloadedMethod(JavaCast(“string”, “Hello”))>

274 Chapter 20 Objects

26 0672324628 CH20 6/8/05 11:10 AM Page 274

Page 298: ColdFusion MX Developer's Cookbook (Developer's Library)

27520.4. Working with Java Objects

20.3. Using Properties on an ObjectYou want to access public properties on an object.

TechniqueUse instanceName.propertyName to read or set the value of a public property.

<cfset math = CreateObject(“java”, “java.lang.Math”)>

<cfset pi = Math.PI>

<cfoutput>#pi#</cfoutput>

CommentsAccessing a property in an object is identical to accessing a key within a structure usingdot notation.The syntax is the same for all types of objects.

The property in this example happens to be the value of PI—a static value.Thisproperty is defined as static final, which in Java means that its value cannot bechanged.

Because PI is read-only, you cannot write to it; however, some properties can be writ-ten to.The syntax for writing to a property is simply instanceName.propertyName= value.

20.4. Working with Java ObjectsYou want to work with Java objects.

TechniqueCreate an object instance with <cfobject> or CreateObject with type=”java”,and then call methods or properties on that object.

<cfset random = CreateObject(“java”, “java.util.Random”)>

<cfset randomSeed = GetTickCount()>

<!--- call the constructor --->

<cfset random.init(randomSeed)>

<cfset randomBool = random.nextBoolean()>

<cfoutput>

Are you feeling lucky? #YesNoFormat(randomBool)#

</cfoutput>

CommentsIn ColdFusion MX, short of Components, Java objects are the natural choice for imple-menting business logic and utility functions. Due to its Java backbone, ColdFusion MXhandles Java objects much more gracefully than it does CORBA or COM objects.

Some of the shortcomings of using Java objects, or any type of object, is due to theway CreateObject and <cfobject> work.There is no way to call the constructor

26 0672324628 CH20 6/8/05 11:10 AM Page 275

Page 299: ColdFusion MX Developer's Cookbook (Developer's Library)

276 Chapter 20 Objects

when the object is created in CreateObject or <cfobject>.The constructor can becalled by using the init function.When ColdFusion receives a call to the initfunction, it calls the constructor.Although this works, it isn’t optimal because two objectsare created (one in CreateObject/<cfobject>, and one in init).

20.5. Working with COM ObjectsYou want to work with COM/DCOM objects.

TechniqueUse the <cfobject> tag to connect to or create an instance of a COM or DCOMobject.

<cftry>

<cfobject type=”COM” action=”connect”

class=”Scripting.FileSystemObject” name=”fileSystem”>

<cfcatch type=”Object”>

<cfobject type=”COM” action=”create” class=”Scripting.FileSystemObject”name=”fileSystem”>

</cfcatch>

</cftry>

<cfset drive = fileSystem.GetDrive(“C”)>

<cfoutput>

C:\ [#drive.VolumeName#]<br>

Total Size: #Round((drive.TotalSize / 1024) / 1024)# MB<br>

Free Space: #Round((drive.FreeSpace / 1024) / 1024)# MB<br>

</cfoutput>

CommentsCOM (Component Object Model) object support is found only in the Windows ver-sions of ColdFusion MX. Being a Windows-centric technology, COM often makes iteasy to interact with Windows components, such as the file system illustrated in thistechnique.

In order for ColdFusion to get an instance of a COM object, it must first be regis-tered.To register a DLL (Dynamic Link Library), use the regsvr32 program. For example:

regsvr32 c:\file.dll

Several COM objects are installed as part of Windows, or as part of service packs such asthe Scripting.FileSystemObject.These objects are already registered, and there-fore should work in a ColdFusion environment without any extra steps.

This technique attempts to connect to an instance of theScripting.FileSystemObject that is already running on the server. If no instance isrunning, the <cfcatch> block executes and creates a new instance of the object.

With an instance to the Scripting.FileSystemObject, you can call methods or

26 0672324628 CH20 6/8/05 11:10 AM Page 276

Page 300: ColdFusion MX Developer's Cookbook (Developer's Library)

access properties exposed by the object. In this case, you call the GetDrive method toretrieve an object with information about the specified drive.

COM object performance has degraded significantly in ColdFusion MX. BecauseColdFusion MX is written in Java, it requires a Java-to-COM bridge to facilitate thecommunication. ColdFusion MX currently uses a third-party Java-to-COM bridgecalled Jintegra.

One of Macromedia’s recommendations to improve performance is to create a Javastub for your COM object.The Java stub is effectively a Java wrapper for the COMobject.A tool that is part of Jintegra, called com2java.exe, automatically generates theJava stub.You can find out more information about this technique in Macromedia’sTechnote #22922.

Rather than waiting for patches and performance tweaks, a good long-term solutionis to rewrite your COM objects in Java. Besides increased performance, you will alsohave an operating system-independent application.

You can connect to objects on your network using DCOM (Distributed ComponentObject Model) by specifying the server attribute in <cfobject>.The server attributemust contain a DNS name (such as www.server.com), an IP address, or a UNC name(such as \\computer).

The CreateObject function can also be used to connect to or create a COMobject instance, as in this example code:

<cfset fileSystem = CreateObject(“COM”, “Scripting.FileSystemObject”)>

20.6. Working with CORBA ObjectsYou want to work with CORBA objects.

TechniqueUse <cfobject> or CreateObject to create an instance of a CORBA object.

<cfobject name=”person” context=”IOR”

class=”c:\ior\person.ior” action=”create” type=”CORBA”>

<cfset person.setName(“Pete”)>

<cfoutput>#person.getName()#</cfoutput>

Person.idl:module PersonApp

{

interface Person

{

string getName();

void setName(in string name);

};

};

27720.6. Working with CORBA Objects

26 0672324628 CH20 6/8/05 11:10 AM Page 277

Page 301: ColdFusion MX Developer's Cookbook (Developer's Library)

278 Chapter 20 Objects

CommentsCommon Object Request Broker Architecture, or CORBA, is a mechanism for devel-oping language-independent distributed applications.The specifications for CORBA aremanaged by the OMG (Object Management Group). CORBA implementations existfor nearly every object-oriented language.

CORBA achieves its language independence by using its own language to describethe object interface.The language is called IDL (Interface Definition Language). Usingthe IDL for verification, all object invocations are passed through an ORB (ObjectRequest Broker).The ORB is responsible for finding and managing a connection to theServant object (the implementation of the object). Servant objects are classes written in aCORBA supported language, and typically bound to CORBA through stub classes.Because all requests go through the ORB, the server and the ORB can reside on differ-ent computers, allowing for the construction of distributed applications.

ColdFusion MX is integrated with Borland VisiBroker 4.5.1 for Java ORB; however,you must download and install VisiBroker from Borland if you want to use CORBAwith ColdFusion MX. Once installed, you have to set up a CORBA connector in theColdFusion Administrator.The ColdFusion MX documentation details the necessaryinstallation steps.

NoteOther ORBs can also be used with ColdFusion MX; however, you must write a connector for the ORB vendor.

Contact Macromedia if you need to use an ORB other than VisiBroker.

Once a connection to the ORB is present, the ORB must be able to find the Servantobjects you want to invoke.There are two supported methods for facilitating this—Naming Services and Interoperable Object References (IOR).The previous code exam-ple uses a file that contains the IOR; the filename is passed through the class attributeof <cfobject>.The context attribute is used to distinguish between using an IORand a CORBA naming service.The following example shows using a naming service:<cfobject

context=”NameService”

class=”Organization/Person”

name=”person”

action=”create”

type=”CORBA”>

The class attribute when context=”NameService” contains the name of theobject; forward slashes (/) are used as delimiters.

An additional attribute of <cfobject> is provided to specify which CORBA con-nector you are using. If you have multiple ORBs registered in the ColdFusion adminis-trator, you need to pass the name of the connection into the locale attribute of <cfobject>. For example, to connect to an ORB called JavaIDL, you use the follow-ing code:

26 0672324628 CH20 6/8/05 11:10 AM Page 278

Page 302: ColdFusion MX Developer's Cookbook (Developer's Library)

27920.6. Working with CORBA Objects

<cfobject

locale=”JavaIDL”

name=”obj”

context=”IOR”

class=”c:\x.ior”

action=”create”

type=”CORBA”>

The CreateObject function can also be used to retrieve object handles from the ORB.

<cfset obj = CreateObject(“CORBA”, “IOR”, “c:\x.ior”, “corbaConnection”)>

The CreateObject function expects the arguments type, context, class, andoptionally locale.

The mapping of IDL to ColdFusion is defined in Table 20.2.

Table 20.2 CORBA IDL to ColdFusion Type Mappings

IDL Type ColdFusion Type Supported

any N/A No

array Array Yes

attribute Object reference Yes

boolean Boolean Yes

char String Yes

constant N/A No

couble Numeric Yes

enum Numeric (zero is the first number in the enumeration) Yes

float Numeric Yes

interface Object reference Yes

long Numeric Yes

longlong N/A No

module N/A Yes

octet String Yes

sequence Array Yes

short Numeric Yes

string String Yes

struct Structure Yes

typedef N/A Yes

union N/A No

unsigned long Number Yes

unsigned longlong N/A No

unsigned short Number Yes

26 0672324628 CH20 6/8/05 11:10 AM Page 279

Page 303: ColdFusion MX Developer's Cookbook (Developer's Library)

280 Chapter 20 Objects

void N/A Yes

wchar String Yeswstring String Yes

Some of the goals of CORBA are very similar to the goals of Web services, such as dis-tributed language-independent objects.Web services are much easier to use inColdFusion MX than CORBA, and may be a better choice. See Chapter 23,“WebServices,” for more information about Web services.

Table 20.2 Continued

IDL Type ColdFusion Type Supported

26 0672324628 CH20 6/8/05 11:10 AM Page 280

Page 304: ColdFusion MX Developer's Cookbook (Developer's Library)

21WDDX

21.0. IntroductionWeb Distributed Data Exchange or WDDX is an XML format for serializing data struc-tures (such as structures, arrays, and queries/recordsets) and data types (such as strings,numbers, booleans, and binary).WDDX was introduced in ColdFusion 4.0 with hopesto promote language-independent data sharing.

Several toolkits have been developed for WDDX in languages other than ColdFusion,such as ASP, Java, JavaScript, Perl, PHP, and C#. However,WDDX has yet to reach wide-spread adoption outside of the ColdFusion community.

WDDX is a good shortcut for converting ColdFusion variables into XML docu-ments.The <cfwddx> tag also makes it easy to represent ColdFusion variables asJavaScript variables.

21.1. CFML to WDDXYou want to convert a CFML data structure into a WDDX XML document.

TechniqueUse the<cfwddx> tag with action=”CFML2WDDX” to convert a ColdFusion structureto WDDX.

<cfset slopes = ArrayNew(1)>

<cfset slopes[1] = “WhiteFace”>

<cfset slopes[2] = “Killington”>

<cfwddx action=”CFML2WDDX” input=”#slopes#” output=”skiWDDX”>

<cfoutput>#HTMLEditFormat(skiWDDX)#</cfoutput>

27 0672324628 CH21 6/8/05 11:10 AM Page 281

Page 305: ColdFusion MX Developer's Cookbook (Developer's Library)

282 Chapter 21 WDDX

CommentsThe code in this technique creates a simple array with two elements, and represents thearray in a standard XML format,WDDX.The following code shows the generatedXML, or WDDX packet, stored in the skiWDDX variable.

<wddxPacket version=’1.0’>

<header/>

<data>

<array length=’2’>

<string>WhiteFace</string>

<string>Killington</string>

</array>

</data>

</wddxPacket>

The generated XML produces enough information for any language to reconstruct thisColdFusion array in its native array.

The key element of this example is the <cfwddx> tag, as it does the work of con-verting the ColdFusion variable into XML.The action attribute of the <cfwddx> tagspecifies the type of translation to be performed.The action in this case is CFML2WDDX.The other three possible values for action are discussed in subsequent sections of thischapter.

When you specify action=”CFML2WDDX”, the tag will naturally convert the inputvariable (identified by the input attribute) into a WDDX packet.The result of the<cfwddx> operation is stored in the variable name designated by the value of the output attribute.Table 21.1 shows some common tag attributes.

Table 21.1 <cfwddx> Tag Attributes

Attribute Meaning

action The type of WDDX translation to perform. Possible values areCFML2WDDX, WDDX2CFML, CFML2JS, and WDDX2JS.

input Input value to serialize or deserialize.

output Name of a variable to store the result of the action. If the actiongenerates JavaScript (if action is CFML2JS or WDDX2JS), and thisattribute is not present, the result will print to the page outputstream.

validate When true, <cfwddx> validates input WDDX against the WDDXDTD. Used with the actions WDDX2CFML and WDDX2JS.

toplevelvariable The JavaScript variable name for the resulting JavaScript object.Only used when action is CFML2JS or WDDX2JS.

usetimezoneinfo When set to true, <cfwddx> represents times in the ISO8601 for-mat.When it’s false, local times are used.

27 0672324628 CH21 6/8/05 11:10 AM Page 282

Page 306: ColdFusion MX Developer's Cookbook (Developer's Library)

28321.2. CFML to JavaScript

This example uses the HTMLEditFormat function to format the XML so that it willdisplay in your browser (it escapes the < and > characters).This is handy for displayingWDDX.

Some Web browsers will format XML in an easy-to-read format.You can let thebrowser know that your returning XML by setting the HTTP response headerContent-Type to text/xml. HTTP response headers can be issued with the<cfheader> tag.

<cfheader name=”Content-Type” value=”text/xml”>

<cfoutput>#skiWDDX#</cfoutput>

In Internet Explorer, the XML is presented in a color-coded format with collapsiblenodes instead of in HTML format.

21.2. CFML to JavaScriptYou want to convert a CFML data structure into a JavaScript object.

TechniqueTo convert a ColdFusion data structure to a JavaScript object, you use the <cfwddx> tagwith the action attribute set to CFML2JS.

<cfset trail = StructNew()>

<cfset trail.isOpen = false>

<cfset trail.name = “BarkEater”>

<cfset trail.opens = CreateDate(2002,11,1)>

<script language=”JavaScript”>

<cfwddx action=”CFML2JS”

input=”#trail#” toplevelvariable=”jsTrail”>

if (jsTrail[“isopen”] == “true”) {

alert(“Trail: “ + jsTrail[“name”] + “ is open.”);

}

else {

alert (“Trail: “ + jsTrail[“name”] +

“ opens on “ + jsTrail[“opens”]);

}

</script>

CommentsConverting from CFML to JavaScript doesn’t actually involve WDDX.The ColdFusionvariable is converted to a JavaScript variable with the <cfwddx> tag. In this technique,the <cfwddx> tag produces the following JavaScript code:

27 0672324628 CH21 6/8/05 11:10 AM Page 283

Page 307: ColdFusion MX Developer's Cookbook (Developer's Library)

284 Chapter 21 WDDX

jsTrail = new Object();

jsTrail[“opens”] = new Date(2002, 10, 1, 0, 0, 0);

jsTrail[“isopen”] = “false”;

jsTrail[“name”] = “BarkEater”;

There are a few things to note about the generated JavaScript code.The isOpen key inthe trail structure is converted to lowercase; this is important because JavaScript vari-ables are case-sensitive, but ColdFusion variables are not.Attempting to read theJavaScript variable jsTrail[“isOpen”] will return a null value.

The ColdFusion variable trail.isOpen is set to a boolean value, false. Howeverthe corresponding JavaScript variable jsTrail[“open”] is set to the string “false”,not a boolean. Because of this, you can’t treat the JavaScript variable as a boolean. Forexample if (jsTrail[“isopen”]) will never evaluate to true, even iftrail.isOpen is set to true.

One feature of the generated JavaScript is that ColdFusion date objects are convertedinto JavaScript date objects, as the value of jsTrail[“opens”] illustrates.

Different ColdFusion data types generate different JavaScript objects.Table 21.2 showssome common JavaScript conversions.

Table 21.2 CFML2JS Conversions

Data Type CFML JavaScript

Array <cfset array = ArrayNew(1)> array = new Array();

<cfset array[1] = “One”> array[0] = “One”;

Date <cfset date = CreateDateTime date = new Date(2000, 0,

(2000,1,1, 12,00,00)> 1, 0, 0, 0);

Query <cfset query = QueryNew query = new (“column”)> WddxRecordset();

<cfset row = QueryAddRow(query)> col0 = new Array();

<cfset QuerySetCell(query, col0[0] = “value”;“column”, “value”, query[“column”] = col0;row)> col0 = null;

String <cfset string = “Value”> string = “Value”;

Structure <cfset struct = StructNew()> struct = new Object();

<cfset struct.key = “Value”> struct[“key”] = “Value”;

Number <cfset number = 8> number = “8”;Boolean <cfset bool = true> bool = “true”;

NoteIf you want to work with query objects in JavaScript, you need to include the WDDX JavaScript library. The

definition for the WddxRecordset JavaScript object is defined in this library, along with a JavaScript to

WDDX serializer. Binary data also requires the JavaScript WddxBinary object to be defined. To include the

library, use the src attribute of the <script> tag—<script src=”/CFIDE/scripts/

wddx.js”></script>.

27 0672324628 CH21 6/8/05 11:10 AM Page 284

Page 308: ColdFusion MX Developer's Cookbook (Developer's Library)

28521.3. WDDX to CFML

21.3. WDDX to CFMLYou want to convert a valid WDDX XML document into a CFML data structure.

TechniqueUse action=”WDDX2CFML” in the <cfwddx> tag to convert WDDX to a ColdFusionvariable.

<cfsavecontent variable=”wddx”>

<wddxPacket version=’1.0’>

<header/>

<data>

<array length=’2’>

<string>WhiteFace</string>

<string>Killington</string>

</array>

</data>

</wddxPacket>

</cfsavecontent>

<cfwddx action=”WDDX2CFML” input=”#wddx#” output=”slopes”>

<cfoutput>

#slopes[1]#

</cfoutput>

CommentsThe process of converting WDDX into ColdFusion data structures is known as deserial-ization.This code is essentially the opposite of the serialization example shown in section21.1.The input attribute receives a WDDX string, and the output attribute holds thename of the resulting ColdFusion variable.

Table 21.3 shows some common data types that are supported, and their WDDX rep-resentations.

Table 21.3 WDDX Representations of Data Types

Data Type WDDX Representation

Array <array length=’1’>

<string>One</string>

</array>

Date <dateTime>2000-1-1T12:0:0-5:0</dateTime>

Query <recordset rowCount=’1’ fieldNames=’column’

27 0672324628 CH21 6/8/05 11:10 AM Page 285

Page 309: ColdFusion MX Developer's Cookbook (Developer's Library)

286 Chapter 21 WDDX

type=’coldfusion.sql.QueryTable’>

<field name=’column’>

<string>value</string>

</field>

</recordset>

String <string>some string</string>

Structure <struct>

<var name=’KEY’>

<string>Value</string>

</var>

</struct>

Number <number>8</number>

Boolean <boolean value=’true’/>

Binary <binary length=’6’>YmluYXJ5</binary>

NoteBinary data in WDDX is encoded in Base64 encoding.

21.4. WDDX to JavaScriptYou want to convert WDDX into a JavaScript object.

TechniqueUse WDDX2JS as the value for the action attribute in <cfwddx> to convert a WDDXstring into JavaScript variables.

<cfsavecontent variable=”wddx”>

<wddxPacket version=’1.0’>

<header/>

<data>

<array length=’2’>

<string>WhiteFace</string>

<string>Killington</string>

</array>

</data>

</wddxPacket>

</cfsavecontent>

Table 21.3 Continued

Data Type WDDX Representation

27 0672324628 CH21 6/8/05 11:10 AM Page 286

Page 310: ColdFusion MX Developer's Cookbook (Developer's Library)

28721.5. Syndicating Content with WDDX

<script language=”JavaScript”>

<cfwddx action=”WDDX2JS” input=”#wddx#”

toplevelvariable=”slopes”>

for (var i=0;i<slopes.length;i++) {

alert(slopes[i]);

}

</script>

CommentsConverting WDDX to JavaScript works just like converting CFML to JavaScript (readsection 21.2). Simply use WDDX2JS as the action, and use the WDDX string in theinput attribute of <cfwddx>.The toplevelvariable attribute stores the name ofthe JavaScript variable.

You can also store the generated JavaScript in a ColdFusion variable using the out-put attribute in <cfwddx>. For example:

<cfwddx action=”WDDX2JS” input=”#wddx#”

output=”slopesJS” toplevelvariable=”slopes”>

<script language=”JavaScript”>

<cfoutput>#slopesJS#</cfoutput>

</script>

21.5. Syndicating Content with WDDXYou want to distribute content using WDDX.

TechniquePublish a page that serializes your content with <cfwddx>, and output the resultingWDDX packet.

skiConditions.cfm:<cfsetting showdebugoutput=”false” enablecfoutputonly=”true”>

<cfset skiConditions = StructNew()>

<cfset skiConditions.currentTemperature = 24>

<cfset skiConditions.weatherForecast = “Snow, and lots of it.”>

<cfset skiConditions.newSnow = 8>

<cfset skiConditions.averageSnowBase = 75>

<cfset skiConditions.trails = QueryNew(“name, isOpen, skillLevel”)>

<cfset row = QueryAddRow(skiConditions.trails)>

<cfset QuerySetCell(skiConditions.trails,

“name”, “Jeremy’s Run”, row)>

<cfset QuerySetCell(skiConditions.trails, “isOpen”, “Yes”, row)>

27 0672324628 CH21 6/8/05 11:10 AM Page 287

Page 311: ColdFusion MX Developer's Cookbook (Developer's Library)

288 Chapter 21 WDDX

<cfset QuerySetCell(skiConditions.trails, “skillLevel”,

“Expert”, row)>

<cfset row = QueryAddRow(skiConditions.trails)>

<cfset QuerySetCell(skiConditions.trails, “name”,

“Avalanche Cliff”, row)>

<cfset QuerySetCell(skiConditions.trails, “isOpen”, “Yes”, row)>

<cfset QuerySetCell(skiConditions.trails, “skillLevel”,

“Expert”, row)>

<cfheader name=”Content-Type” value=”text/xml”>

<cfwddx action=”CFML2WDDX” input=”#skiConditions#” output=”wddx”>

<cfoutput>

<?xml version=”1.0”?>

#wddx#

</cfoutput>

CommentsSyndicating content with WDDX involves creating a Web page that outputs WDDX.The example publishes ski conditions for a factitious ski resort called “ColdFusionMountain.”

On the first line of the example is a <cfsetting> tag. It ensures that the only thingyou output is XML by disabling debugging output, and output that isn’t inside the<cfoutput> tags.

NoteWhite space is ignored in WDDX, so it’s not necessary to use the <cfsetting> tag to limit output to the

body of <cfoutput> tags. However, any characters that are output accidentally may cause problems with

parsers deserializing the content.

Next, you create a structure that holds the information you are to syndicate.Thetrails key in the skiConditions structure holds a query of trial information.Thisquery is populated manually with the QueryNew, QueryAddRow, and QuerySetCellfunctions but normally all the information you’re syndicating would come from a data-base or some other dynamic source.

The <cfheader> tag sets the page Content-Type to text/xml in order to allowbrowsers that format XML to do so.

Finally, you serialize the structure into WDDX with <cfwddx> and output it.AnXML document declaration <?xml version=”1.0”?> is prepended to the WDDX.You might also consider adding the WDDX Document Type Declaration (DTD) to yourXML document to enable XML validation.

27 0672324628 CH21 6/8/05 11:10 AM Page 288

Page 312: ColdFusion MX Developer's Cookbook (Developer's Library)

28921.5. Syndicating Content with WDDX

NoteThe WDDX DTD, along with more information about WDDX, can be found at www.openwddx.org. The

OpenWDDX Web site is an effort to promote WDDX as an open interface for exchanging data on the Web.

Once the WDDX is published it can be consumed by anyone with access to it, on anyserver.WDDX is typically consumed with a HTTP client such as <cfhttp>.

<cfif NOT IsDefined(“application.skiConditions”)

OR IsDefined(“url.update”)>

<!--- retrieve the WDDX feed --->

<cfset skiConditionsURL =

“http://skicoldfusion.com/skiConditions.cfm”>

<cfhttp url=”#skiConditionsURL#”></cfhttp>

<cfwddx action=”WDDX2CFML” input=”#CFHTTP.FileContent#”

output=”application.skiConditions”>

</cfif>

<b>Current Ski Conditions at ColdFusion Mountain</b><p>

<cfoutput>

Current Temperature: #application.skiConditions.currentTemperature#<br>

Weather Forecast: #application.skiConditions.weatherForecast#<br>

New Snow: #application.skiConditions.newSnow# inches<br>

Average Snow Base: #application.skiConditions.averageSnowBase# inches<br>

</cfoutput>

</p>

<b>Trail’s</b><p>

<cfoutput query=”application.skiConditions.trails”>

#application.skiConditions.trails.name#

(#application.skiConditions.trails.skillLevel#):

<cfif application.skiConditions.trails.isOpen>Open

<cfelse>Closed

</cfif><br>

</cfoutput>

</p>

The output of this example is as follows:

Current Ski Conditions at ColdFusion Mountain

Current Temperature: 24

Weather Forecast: Snow, and lots of it.

New Snow: 8 inches

Average Snow Base: 75 inches

Trail’s

Jeremy’s Run (Expert): Open

Avalanche Cliff (Expert): Open

27 0672324628 CH21 6/8/05 11:10 AM Page 289

Page 313: ColdFusion MX Developer's Cookbook (Developer's Library)

290 Chapter 21 WDDX

When the WDDX is deserialized back into a ColdFusion variable, you can manipulate itas you want. In this case, the example shows an HTML page with a summary of the skiconditions.

The preceding code example caches the skiConditions structure in an application scoped variable so the WDDX doesn’t need to be retrieved every time the ski conditions are requested. Caching the feed benefits both the contentprovider and the content consumer with less bandwidth consumption.

Web Services are another good way to share data between servers; they are discussedin Chapter 23,“Web Services.”

21.6. Converting a Java Object into WDDXYou want to serialize a Java data structure into WDDX XML.

TechniqueUse the WddxSerializer class to convert a Java object to WDDX.

import com.allaire.wddx.WddxSerializer;

import java.util.Hashtable;

import java.util.Vector;

import java.util.Date;

import java.io.StringWriter;

public class WDDXSerializerExample

{

public static final void main(String[] args)

throws java.io.IOException

{

Hashtable hash = new Hashtable();

hash.put(“key”, “value”);

Vector v = new Vector();

v.add(new Date());

v.add(new Integer(8));

hash.put(“array”, v);

WddxSerializer serializer = new WddxSerializer();

StringWriter writer = new StringWriter();

serializer.serialize(hash, writer);

27 0672324628 CH21 6/8/05 11:10 AM Page 290

Page 314: ColdFusion MX Developer's Cookbook (Developer's Library)

29121.6. Converting a Java Object into WDDX

System.out.println(writer.toString());

}

}

CommentsThe WddxSerializer class is included in a Java archive file called wddx.jar that isincluded in the WDDX SDK from www.openwddx.org.The WddxSerializer class,when given an object, will serialize the object in the WDDX format.Table 21.4 showsthe mapping of Java data structures to their respective WDDX representation.

Table 21.4 WDDX Representations of Java Data Structure

WDDX Type Java Type

array Java.util.Vector

dateTime Java.util.Date

recordSet com.allaire.util.RecordSet

string Java.lang.String

struct Java.util.Dictionary

number Java.lang.Integer

boolean Java.lang.Boolean

number Java.lang.Byte

number Java.lang.Float

number Java.lang.Double

number Java.lang.Short

string Java.lang.Character

array Java.util.List

struct Java.util.Map

The serialize method of the WddxSerializer class takes two arguments.The first argu-ment is an object of type java.lang.Object that you would like to serialize intoWDDX.The second argument is used to pass a java.io.Writer to the serializer.Theserialized content is then written to the java.io.Writer.

Because the WddxSerializer can only serialize a java.lang.Object, you cannotdirectly serialize a primitive data type such as int, float, or an array. Instead primi-tive data types must be converted to their java.lang counterparts, such asjava.lang.Integer and java.lang.Float.Arrays must be converted to ajava.util.List or a java.util.Vector.

Due to polymorphism in Java, the WddxSerializer can serialize any object thatinherits from any of the Java classes listed in Table 21.4. For example, thejava.util.Hashtable inherits from java.util.Dictionary; a hashtable was usedin the previous example.

27 0672324628 CH21 6/8/05 11:10 AM Page 291

Page 315: ColdFusion MX Developer's Cookbook (Developer's Library)

292 Chapter 21 WDDX

The WDDX API contained within wddx.jar is written in a manor that allows youto create your own serializer for your own data structures.To create your own WDDXobject serializer, you must create a class that implements the com.allaire.wddx.WddxObjectSerializer interface.The WddxObjectSerializer interface has onemethod that you must implement. It’s called writeObject and takes a com.allaire.wddx.WddxOutputStream and a java.lang.Object as inputs and has a voidreturn type. Once your WDDX object serializer is implemented, you can add it to the instance of the com.allaire.wddx.WddxObjectSerializerFactoryclass that your WddxSerializer instance is using.This is done using thegetSerializerFactory or the static getDefaultSerializerFactory method in the WddxSerializer class.

21.7. Deserializing WDDX in JavaYou want to create java objects from a WDDX packet.

TechniqueUse the WddxDeserializer class to convert WDDX to java objects.

import java.io.StringReader;

import java.io.IOException;

import org.xml.sax.InputSource;

import com.allaire.wddx.WddxDeserializer;

import com.allaire.wddx.WddxDeserializationException;

import com.allaire.util.RecordSet;

import java.io.FileInputStream;

import java.util.Dictionary;

public class WDDXDeserializerExample

{

public static final void main(String[] args)

throws Exception

{

FileInputStream fin =

new FileInputStream(“c:/skiConditions.wddx”);

InputSource in = new InputSource(fin);

Object obj = deserializeWDDX(in);

if (!(obj instanceof Dictionary)) {

throw new Exception(“obj not a dictionary”);

}

Dictionary ski = (Dictionary)obj;

System.out.println(“Temp: “

27 0672324628 CH21 6/8/05 11:10 AM Page 292

Page 316: ColdFusion MX Developer's Cookbook (Developer's Library)

29321.7. Deserializing WDDX in Java

+ ski.get(“CURRENTTEMPERATURE”));

System.out.println(“New Snow: “

+ ski.get(“NEWSNOW”));

System.out.println(“Forecast: “

+ ski.get(“WEATHERFORECAST”));

System.out.println(“Avg Base: “

+ ski.get(“AVERAGESNOWBASE”));

Object trailObj = ski.get(“TRAILS”);

if (! (trailObj instanceof RecordSet) ) {

throw new Exception(“trails is not a query”);

}

RecordSet trails = (RecordSet)trailObj;

int rows = trails.getRowCount();

int name = trails.findColumn(“name”);

int isOpen = trails.findColumn(“isOpen”);

int skill = trails.findColumn(“skillLevel”);

System.out.println(“Trails:”);

StringBuffer sb = new StringBuffer(32);

for (int row=0;row<rows;row++) {

sb.setLength(0);

sb.append(trails.getField(row, name));

sb.append(“ - open: “);

sb.append(trails.getField(row, isOpen));

sb.append(“ - skill level: “);

sb.append(trails.getField(row, skill));

System.out.println(sb.toString());

}

}

public static Object deserializeWDDX(String wddxPacket)

throws WddxDeserializationException, IOException

{

InputSource in =

new InputSource(new StringReader(wddxPacket));

return deserializeWDDX(in);

}

public static Object deserializeWDDX(InputSource in)

throws WddxDeserializationException, IOException

{

WddxDeserializer deserializer =

27 0672324628 CH21 6/8/05 11:10 AM Page 293

Page 317: ColdFusion MX Developer's Cookbook (Developer's Library)

294 Chapter 21 WDDX

new WddxDeserializer(“org.apache.xerces.parsers.SAXParser”);

// Deserialize the WDDX packet

return deserializer.deserialize(in);

}

}

CommentsThis example outputs the ski conditions WDDX feed presented in section 21.5.TheWddxDeserializer class is used to convert the WDDX packet into Java objects, and isfound in wddx.jar from www.openwddx.org.The WddxDeserializer constructortakes the name of a Sax Parser (a class that implements the org.xml.sax.Parserinterface). In this case, we specified org.apache.xerses.parsers.SAXParserbecause we are using Xerces from the Apache Foundation.

To deserialize the WDDX packet, the deserialize method is invoked in theWddxDeserializer class.The deserialize method takes an org.xml.sax.InputSource object as an input.The org.xml.sax.InputSource class constructor takes a java.io.InputStream as an argument. In this example we pass an instance of a java.io.FileInputStream to create the input source.

The deserialize method returns a java.lang.Object that represents the contentsof the WDDX packet.The next step is typically to cast the object into a type that youcan use.This example does just that, but before the object is cast the type of the object isverified by determining whether it is an instance of a java.util.Dictionary.Data is extracted from the recordSet object (the trails query) using the com.allaire.util.RecordSet class.The methods for the com.allaire.util.RecordSet class are defined in Table 21.5.

Table 21.5 The com.allaire.util.RecordSet Interface

Method Description

int addRows(int rows) Adds rows to the record set and returns the row index.

int addColumn(String name) Adds a column with the specified name and returns thecolumn index.

int findColumn(String name) Returns the column index given the column name.

int getColumnCount() Returns the number of columns in the record set.

String[] getColumnNames() Returns an array holding the names of each column inthe record set.

Object getField(int row, Returns the value of a cell in the record set.int column)

int getRowCount() Returns the number of rows in the record set.void setField(int row, Sets the value of a cell in the record set.int column, Object value)

27 0672324628 CH21 6/8/05 11:10 AM Page 294

Page 318: ColdFusion MX Developer's Cookbook (Developer's Library)

22XML

22.0. IntroductionThe Xtensible Markup Language (XML) has quickly become the data interchange for-mat of choice. Software systems can now use XML as a communications vehicle withother systems, regardless of their platform or implementation.WDDX and SOAP aretwo excellent examples of how XML can be used to serialize and transmit complex dataobjects.

Prior to the ColdFusion MX release, CF developers who wanted to use XML wereforced to do so manually. Fortunately, the ColdFusion MX release includes a robust pro-gramming library for creating, modifying, and interacting with XML documents.

22.1. Creating an XML Object with the<cfxml> Tag

You want to create an XML object manually.

TechniqueUse the <cfxml> tag to create and initialize a ColdFusion XML structure.

<cfscript>

person = structNew();

person.firstname = “Albert”;

person.lastname = “Einstein”;

person.city = “Princeton”;

person.state = “New Jersey”;

person.country = “USA”;

</cfscript>

28 0672324628 CH22 6/8/05 11:10 AM Page 295

Page 319: ColdFusion MX Developer's Cookbook (Developer's Library)

296 Chapter 22 XML

<cfxml variable=”personXML”>

<person>

<cfoutput>

<firstName>#person.firstName#</firstName>

<lastName>#person.lastName#</lastName>

<city>#person.city#</city>

<state>#person.state#</state>

<country>#person.country#</country>

</cfoutput>

</person>

</cfxml>

<cfdump var=”#personXML#”>

CommentsThe <cfxml> tag is an excellent way to create and initialize an XML document objectquickly. If you have ever used the XML DOM API to create an XML document object,you know that this method can be a laborious process.You have to first create a newobject for each element, attribute, and text value in the XML tree and then piece themtogether.You can bypass this process by using the <cfxml> tag to initialize an XMLobject with a string representing the XML document you want to create.

The previous example uses this technique to create an XML representation of a per-son structure.The example uses text to fill out the structure of the XML documentwithin the body of the <cfxml> tag and uses ColdFusion expressions to extract the val-ues from a CFML structure to be used as text nodes.

22.2. Creating an XML Object with theXmlNew() Function

You want to create an XML object programmatically.

TechniqueUse the XMLNew() and XMLElemNew() functions to build an XML object piece bypiece.

<cfscript>

person = structNew();

person.firstname = “Albert”;

person.lastname = “Einstein”;

person.city = “Princeton”;

person.state = “New Jersey”;

28 0672324628 CH22 6/8/05 11:10 AM Page 296

Page 320: ColdFusion MX Developer's Cookbook (Developer's Library)

29722.2. Creating an XML Object with the XmlNew() Function

person.country = “USA”;

</cfscript>

<cfscript>

personXML = XmlNew();

personXML.xmlRoot = XmlElemNew(personXML, “person”);

personXML.xmlRoot.XmlChildren[1] = XmlElemNew(personXML, “firstName”);

personXML.xmlRoot.XmlChildren[1].XmlText = person.firstName;

personXML.xmlRoot.XmlChildren[2] = XmlElemNew(personXML, “lastName”);

personXML.xmlRoot.XmlChildren[2].XmlText = person.lastName;

personXML.xmlRoot.XmlChildren[3] = XmlElemNew(personXML, “city”);

personXML.xmlRoot.XmlChildren[3].XmlText = person.city;

personXML.xmlRoot.XmlChildren[4] = XmlElemNew(personXML, “state”);

personXML.xmlRoot.XmlChildren[4].XmlText = person.state;

personXML.xmlRoot.XmlChildren[5] = XmlElemNew(personXML, “country”);

personXML.xmlRoot.XmlChildren[5].XmlText = person.country;

</cfscript>

<cfdump var=”#personXML#”>

CommentsThere are two types of XML objects in ColdFusion MX: elements and documents.Anelement object represents a single element node within an XML tree. Generally, an ele-ment contains a name, a list of attributes, a text value, and/or a collection of child ele-ments. Element objects belonging to a single XML document are assembled into a doc-ument object.The document object’s job is to maintain a reference to the root node inthe XML document tree.

To support the creation of these objects, ColdFusion MX includes two additions toits function library: XmlNew() and XmlElemNew(). XmlNew() creates and returns anew ColdFusion XML document object, whereas XmlElemNew() creates and returns achild element that can be inserted anywhere within the XML document.XmlElemNew() accepts two arguments.The first, xmlObj, is a valid CFML XML object(such as the one created with XmlNew()).The second, childName, is the name of thechild element to be created.

CFML XML document and element objects have a number of properties that youshould be aware of.These are listed in Tables 22.1 and 22.2.

Table 22.1 XML Document Properties

Key Type Value

XmlComment String A comment to be associated with this XML document object.XmlRoot Element The root element in the XML document.The root element cor-

responds to the document’s root tag.

28 0672324628 CH22 6/8/05 11:10 AM Page 297

Page 321: ColdFusion MX Developer's Cookbook (Developer's Library)

298 Chapter 22 XML

Table 22.2 XML Element Properties

Key Type Value

XmlAttributes Structure A structure of name/value pairs representing an element’sattribute list.

XmlChildren Array An array of child elements.This array can be manipulateddirectly to maintain the element’s children.

XmlComment String A string representing a comment to be associated with thiselement.

XmlName String The name of this element.

XmlNsPrefix String The namespace prefix for this element.

XmlNsURI String The namespace URL for this element.XmlText String The text value for this element.

22.3. Creating an XML Object from AnotherXML Object

You want to create an XML object using another object as a starting point.

TechniqueUse the Duplicate() function to copy an XML document to another XML docu-ment.

<cfset personXML2 = Duplicate(personXML)>

<cfset personXML2.xmlRoot.XmlChildren[1].XmlText = “Johnathon”>

<cfdump var=”#personXML#”>

<cfdump var=”#personXML2#”>

CommentsThe Duplicate() function is a standard function that lets you copy the contents ofany CFML variable.The Duplicate() function ensures that the copied value containsno references to the original variable.This is shown in the technique above, in which thetext value of a node is altered in the copied XML document. Dumping the contents ofboth structures reveals that the change did not affect the original document.

28 0672324628 CH22 6/8/05 11:10 AM Page 298

Page 322: ColdFusion MX Developer's Cookbook (Developer's Library)

29922.5. Accessing Attributes

22.4. Parsing an XML DocumentYou want to parse an XML document into a CFML XML document object.

TechniqueUse the XmlParse() function to parse an XML text string into a ColdFusion XMLdocument object.

<cfset filename = GetDirectoryFromPath(GetCurrentTemplatePath())&”person.xml”>

<cffile action=”read” file=”#filename#” variable=”xmltext”>

<cfset personXML = XmlParse(xmltext)>

<cfdump var=”#personXML#”>

CommentsThe XmlParse() function lets you convert an XML document in text format into anXML document object.The XML text can come from any source available toColdFusion, such as an HTTP request result, a database query, or a file.TheXmlParse() function accepts the XML string as its only argument and returns aCFML XML document object as its result.

22.5. Accessing AttributesYou want to add or modify an XML node’s attributes.

TechniqueModify an XML element’s attributes collection by modifying the XmlAttributes

CFML structure.

<cfparam name=”person”>

<cfxml variable=”personXML”>

<person>

<cfoutput>

<firstName>#person.firstName#</firstName>

<lastName>#person.lastName#</lastName>

<city>#person.city#</city>

<state>#person.state#</state>

<country>#person.country#</country>

</cfoutput>

</person>

</cfxml>

<cfset personXML.xmlRoot.xmlAttributes.id = “10012”>

<cfdump var=”#personXML#”>

28 0672324628 CH22 6/8/05 11:10 AM Page 299

Page 323: ColdFusion MX Developer's Cookbook (Developer's Library)

CommentsAll ColdFusion MX element objects contain an implicit structure calledXmlAttributes.This CFML structure contains the name/value pairs of the node’sattributes collection.Adding and modifying the element’s attributes is as easy as modify-ing the CFML structure. In the previous technique, an ID attribute is added to the<person> element by setting an id property in the xmlAttributes structure.

22.6. Accessing ChildrenYou want to add or modify one or more children of an XML node.

TechniqueUse an element’s XmlChildren array to modify its list of children.

<cfscript>

myXML = XmlNew();

myXML.xmlRoot = XmlElemNew(myXML, “myRoot”);

myXML.xmlRoot.XmlChildren[1] = XmlElemNew(myXML, “childNode”);

myXML.xmlRoot.XmlChildren[1].XmlText = “Child Node Text”;

</cfscript>

<cfdump var=”#myXML#”>

CommentsAll element objects contain an XmlChildren property, which is an array of its childrenelement objects.This array can be accessed and modified directly. In the previous tech-nique, a child is added to the root node with the following statement:

myXML.xmlRoot.XmlChildren[1] = XmlElemNew(myXML, “childNode”);

22.7. Accessing Inner TextYou want to access an XML node’s inner text value.

TechniqueUse an XML element’s XmlText property to set its text value.

<cfscript>

myXML = XmlNew();

myXML.xmlRoot = XmlElemNew(myXML, “myRoot”);

myXML.xmlRoot.XmlText = “This is the inner text”;

</cfscript>

<cfdump var=”#myXML#”>

300 Chapter 22 XML

28 0672324628 CH22 6/8/05 11:10 AM Page 300

Page 324: ColdFusion MX Developer's Cookbook (Developer's Library)

30122.8. Searching XML with XPath

CommentsThe XmlText property of an XML element represents the text that can be found in thetag body.All XML elements contain this property and you can set it directly in yourcode.The previous technique sets the root node’s inner text value to the string “Thisis the inner text”.

22.8. Searching XML with XPathYou want to search an XML document.

TechniqueUse the XmlSearch() CFML function and the XPath query language to search anXML document.

<cfxml variable=”capitalsXML”>

<capitals>

<capital>

<name>Raleigh</name>

<state>NC</state>

</capital>

<capital>

<name>Augusta</name>

<state>GA</state>

</capital>

<capital>

<name>Columbia</name>

<state>SC</state>

</capital>

</capitals>

</cfxml>

<cfset results = XmlSearch(capitalsXML, “/capitals/capital[state=’NC’]”)>

<cfdump var=”#results#”>

CommentsThe XPath query language is a powerful tool for dissecting and querying XML docu-ments. Because a full discussion of this language is beyond the scope of this book, moreinformation about XPath can be found at the W3C Web site athttp://www.w3.org/TR/xpath.

ColdFusion MX supports XPath queries via the new XmlSearch() function.Thefunction takes two arguments: the XML document object to search and the XPathexpression to search for.The function returns a CFML array of XML element objects.

28 0672324628 CH22 6/8/05 11:10 AM Page 301

Page 325: ColdFusion MX Developer's Cookbook (Developer's Library)

302 Chapter 22 XML

The previous technique searches a list of state capitals for the capital city of NorthCarolina.

The XPath expression “/capitals/capital[state=’NC’]” searches the chil-dren of the capitals root node for all capital elements that contain a state childnode with the text value of “NC”.The result of this query is an array with a single valuethat is the XML element object of the capital element corresponding to Raleigh, NC.

22.9. XSL TransformationsYou want to transform one XML document into another XML documentusing an XSL transformation.

TechniqueUse the XmlTransform() function and the XSLT transformation language to trans-form XML documents.

<cfxml variable=”people”>

<people>

<person>

<firstName>John</firstName>

<lastName>Smith</lastName>

<city>New York</city>

<state>NY</state>

<country>USA</country>

</person>

<person>

<firstName>Steve</firstName>

<lastName>Jones</lastName>

<city>Boston</city>

<state>MA</state>

<country>USA</country>

</person>

</people>

</cfxml>

<cfsavecontent variable=”xslt”>

<xsl:stylesheet

xmlns:xsl=http://www.w3.org/1999/XSL/Transform

version=”1.0”>

<xsl:output method=”html”/>

<xsl:template match=”/”>

<html>

<body>

28 0672324628 CH22 6/8/05 11:10 AM Page 302

Page 326: ColdFusion MX Developer's Cookbook (Developer's Library)

30322.9. XSL Transformations

<xsl:apply-templates />

</body>

</html>

</xsl:template>

<xsl:template match=”people”>

<table>

<tr>

<th>First Name</th>

<th>Last Name</th>

<th>City</th>

<th>State</th>

<th>Country</th>

</tr>

<xsl:apply-templates />

</table>

</xsl:template>

<xsl:template match=”person”>

<tr>

<xsl:choose>

<xsl:when test=”position() mod 4 > 0”>

<xsl:attribute name=”bgcolor”>ffffff</xsl:attribute>

</xsl:when>

<xsl:otherwise>

<xsl:attribute name=”bgcolor”>a1a1a1</xsl:attribute>

</xsl:otherwise>

</xsl:choose>

<td><xsl:value-of select=”firstName”/></td>

<td><xsl:value-of select=”lastName”/></td>

<td><xsl:value-of select=”city”/></td>

<td><xsl:value-of select=”state”/></td>

<td><xsl:value-of select=”country”/></td>

</tr>

</xsl:template>

</xsl:stylesheet>

</cfsavecontent>

<cfset result = XmlTransform(people,xslt)>

<cfoutput>#result#</cfoutput>

CommentsThe XSL Transformation language (XSLT) is an XML-based language that lets you con-vert one XML document into another.This may sound trivial, but its implications are

28 0672324628 CH22 6/8/05 11:10 AM Page 303

Page 327: ColdFusion MX Developer's Cookbook (Developer's Library)

304 Chapter 22 XML

far-reaching. Like XPath, the XSLT specification is maintained by the W3C and can befound at http://www.w3.org/TR/xslt. XSLT uses a combination of its own tagsyntax and the XPath expression language to enable the recursive or iterative construc-tion of a new XML document.

One of the most compelling uses for XML transformations in your ColdFusionapplications is for separating presentation from content. By using XML to model thecontent in your Web pages, you can reduce the pages to their barest essentials, therebyremoving all HTML formatting.The HTML presentation rules can then be relocatedinto one or more XSLT transformation pages.Thus, you divide the job of page creationneatly into its natural components: page creation and aesthetic formatting.

The previous technique provides a complete example of transforming a generic XMLdocument into an HTML document suitable for display in a Web browser.The first sec-tion of the technique uses the <cfxml> function to create an XML document that con-tains a list of names and addresses.The second section of the example creates an XSLTstylesheet and saves it in a variable called xslt. Finally, the following expression

XmlTransform(people,xslt)

applies the rules defined in the XSLT transformation to the people XML documentand returns the result, which is subsequently inserted in the page.

28 0672324628 CH22 6/8/05 11:10 AM Page 304

Page 328: ColdFusion MX Developer's Cookbook (Developer's Library)

23Web Services

23.0. IntroductionColdFusion MX provides one of the simplest platforms for invoking and deploying Webservices. Not to mistake simplicity with weakness, the ColdFusion MX Web Servicesplatform is also robust, and based on the Apache Axis SOAP (Simple Object AccessProtocol) implementation.

Discussions of Web services often include the acronyms WSDL and SOAP. SOAP isan XML messaging protocol used most frequently when the messages are sent over theHTTP or HTTPS protocols (however, other transport protocols, such as SMTP, can beused). SOAP, in and of itself, is not a Web service; it is simply one way to leverage themby providing message encoding and remote procedure calls (RPC).WSDL, the WebServices Description Language, is used to describe the capabilities of the Web service andthe formats for exchanging data. From the WSDL, a client has all the information need-ed to communicate with the Web service.

The key advantage to using Web services is interoperability.Web services are exposedthrough standard protocols such as HTTP, and work with standard data formats such asXML.Any platform that can send a message to the service and interpret its response caninteroperate. Most languages have toolkits, or APIs, for serving or consuming WebServices.This includes Java, C#/.NET, JavaScript, Perl, PHP, and several more.

By leveraging XML,Web services provide a standards-based wrapper around propri-etary platforms.With broad support from all major software vendors, it’s clear that Webservices will be around for a few years.

29 0672324628 CH23 6/8/05 11:11 AM Page 305

Page 329: ColdFusion MX Developer's Cookbook (Developer's Library)

306 CHAPTER 23 Web Services

23.1. Invoking a Web Service with CFINVOKEYou want to invoke a method on a Web service.

TechniqueUse the <cfinvoke> tag to invoke a single method on a Web service.

<cfinvoke

webservice=

“http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl”

method=”getQuote”

symbol=”MACR”

returnvariable=”quote”>

<cfoutput>Current Stock Price for MACR is: #quote#</cfoutput>

CommentsThe <cfinvoke> tag is used to call a method on an object.When used with the webservice attribute, <cfinvoke> can be used to call methods on Web services.Thewebservice attribute in this technique holds a URL to a Web Services DescriptionLanguage (WSDL) XML document.As its name suggests, a WSDL file describes allaspects of a Web service, including object definitions, the location of the remote object,and a means, or protocol, to reach the object.

This example makes use of a public Web service to retrieve a stock quote. Because aWeb service can have multiple methods that you can invoke, the method name to invokeis specified with the method attribute.

Passing arguments to methods can be accomplished in three ways.This techniquepasses the argument as an attribute in the <cfinvoke> tag, in this case the symbolattribute.The attribute must have the same name as the argument defined in the WSDLfile.

An alternative method to pass arguments to a <cfinvoke> request involves passing a structure to the argumentcollection attribute.The third way to pass arguments to <cfinvoke> uses the <cfinvokeargument> tag as the following code sample illustrates.

<cfinvoke

webservice=

“http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl”

method=”getQuote”

returnvariable=”quote”>

<cfinvokeargument name=”symbol” value=”MACR”>

</cfinvoke>

The returnvariable attribute in <cfinvoke> defines the name of a variable holdingthe result of the method call.

29 0672324628 CH23 6/8/05 11:11 AM Page 306

Page 330: ColdFusion MX Developer's Cookbook (Developer's Library)

30723.2. Creating an Instance of a Web Service

Not all Web services are intended to be public. If you need to invoke a Web servicethat requires a username and password, you can use the username and passwordattributes of <cfinvoke> to do so.You can manage usernames and passwords for Webservices in the ColdFusion Administrator by creating Web services mappings (map anarbitrary name to WSDL file), and entering a username and password. If a username andpassword are supplied in both the ColdFusion Administrator and the <cfinvoke> tag,the <cfinvoke> tag takes precedence.

The getQuote method returns a value of type xsd:float; this value is automati-cally converted to a string or numeric by ColdFusion. See Table 23.1 for conversionbetween ColdFusion and WSDL types.Any complex type received by a Web service isconverted into a ColdFusion structure.

NoteThe <cfdump> tag is an easy way to inspect what a Web service returned. It’s especially handy when deal-

ing with complex types.

23.2. Creating an Instance of a Web ServiceYou want to store an instance of a Web service in order to perform multiplemethod calls on it.

TechniqueUse the <cfobject> tag or CreateObject function to create an instance of anobject.

<cfobject

webservice=”http://www.xmethods.net/sd/2001/TemperatureService.wsdl”

name=”tempService”>

<cfoutput>

Temperatures<br>

Sauquoit, NY: #tempService.getTemp(“13456”)#<br>

Anchorage, AK: #tempService.getTemp(“99501”)#<br>

</cfoutput>

CommentsIf you want to invoke multiple methods on a Web service or invoke the same methodmultiple times, it is a good idea to store an instance of the Web service in a ColdFusionvariable.

An instance of a Web service can be created with the <cfobject> tag via the webservice attribute.The webservice attribute is used to pass either a URL to aWSDL file, or the name of a Web service alias defined in the ColdFusion Administrator.

29 0672324628 CH23 6/8/05 11:11 AM Page 307

Page 331: ColdFusion MX Developer's Cookbook (Developer's Library)

308 CHAPTER 23 Web Services

You can also use the CreateObject function to create an instance of a Web service,as shown here:

<cfset service = CreateObject(“webservice”, “http://site.com/wsdl”)>

The first argument of CreateObject specifies the type of object to create. For a Webservice, you use the string “webservice”.The second argument of theCreateObject function is the WSDL URL or Web Service name.

Once a handle to the Web service is obtained, you can call methods on the Web serv-ice using the instance.methodName(arguments) notation (shown in the previouscode example), or using the <cfinvoke> tag shown here:

<cfinvoke

webservice=”#tempService#”

method=”getTemp”

zipcode=”13456”

returnvariable=”temp”>

To invoke an instance method with <cfinvoke>, you pass the variable holding theinstance (in this case, the variable tempService).

23.3. Writing a Web ServiceYou want to create a Web service with ColdFusion.

TechniqueTo write a Web service, create a CFC method with access type “remote”.

<cfcomponent>

<cffunction access=”remote”

name=”getDogYears”

output=”false”

returntype=”numeric”>

<cfargument name=”humanYears” type=”numeric” required=”true”>

<cfreturn arguments.humanYears * 7>

</cffunction>

</cfcomponent>

CommentsWriting a Web service is surprisingly simple if you’re already familiar with ColdFusionComponents (covered in Chapter 19,“Components”) and user-defined functions

29 0672324628 CH23 6/8/05 11:11 AM Page 308

Page 332: ColdFusion MX Developer's Cookbook (Developer's Library)

30923.4. Using Properties

(covered in Chapter 16,“User-Defined Functions”). By using access=”remote” in the<cffunction> tag within a CFC, the method is exposed as a Web service.

There are a few rules for Web services that differ from CFCs and UDFs. First, thereturntype attribute must be present in the <cffunction> tag. Because most lan-guages, unlike ColdFusion, are strongly typed, this is a requirement for Web services. Ifthe Web service does not return a value, use the return type “void”.Web services alsodo not allow optional function arguments.

NoteThe ColdFusion compiler does not warn you when you omit the returntype, or attempt to use an

optional argument within a remote method. You will, however, receive errors when you attempt to invoke

the Web service.

23.4. Using PropertiesYou want to define your own data types for your Web service.

TechniqueUse the <cfproperty> tag to create your own complex types for your Web services.

Flight.cfc:<cfcomponent>

<cfproperty name=”departs” type=”date”>

<cfproperty name=”arrives” type=”date”>

<cfproperty name=”departsFrom” type=”string”>

<cfproperty name=”destination” type=”string”>

<cfproperty name=”price” type=”numeric”>

<cfproperty name=”flightNumber” type=”numeric”>

</cfcomponent>

TravelService.cfc:<cfcomponent>

<cffunction access=”remote”

name=”findFlight” returntype=”Flight” output=”false”>

<cfargument name=”departs” type=”date” required=”true”>

<cfargument name=”arrives” type=”date” required=”true”>

<cfargument name=”departsFrom” type=”string” required=”true”>

<cfargument name=”destination” type=”string” required=”true”>

<!--- lookup matching flights in db, then populate flight info --->

<cfset flight = CreateObject(“component”, “Flight”)>

<cfset flight.departs = CreateDateTime(2003,3,6,18,0,0)>

29 0672324628 CH23 6/8/05 11:11 AM Page 309

Page 333: ColdFusion MX Developer's Cookbook (Developer's Library)

310 CHAPTER 23 Web Services

<cfset flight.arrives = CreateDateTime(2003,3,6,22,0,0)>

<cfset flight.departsFrom = “SYR”>

<cfset flight.destination = “DEN”>

<cfset flight.price = 200>

<cfset flight.flightNumber = 123>

</cffunction>

</cfcomponent>

CommentsWeb services built with ColdFusion can return custom data types, represented by a CFCusing <cfproperty> tags.The <cfproperty> tag is used to describe property namesand data types. By specifying multiple properties within a component, you can createyour own data type.This technique creates a data type called Flight that stores infor-mation about a flight. Properties can be accessed with dot notation, as shown in thefindFlight method of the TravelService CFC.

Although you can simply return a structure of values, using properties is a betterapproach. Properties allow you to return a data structure with documented elements anddata types. Structures can represent different data types and a variable number of ele-ments.

The findFlight method in the TravelServiceWeb service returns a Flightobject. In WSDL, the structure of the Flight Component is defined in XML schema asfollows.

<complexType name=”flight”>

<sequence>

<element name=”Destination” nillable=”true” type=”xsd:string” />

<element name=”Departs” nillable=”true” type=”xsd:dateTime” />

<element name=”Price” nillable=”true” type=”SOAP-ENC:double” />

<element name=”DepartsFrom” nillable=”true” type=”xsd:string” />

<element name=”Arrives” nillable=”true” type=”xsd:dateTime” />

<element name=”FlightNumber” nillable=”true” type=”SOAP-ENC:double” />

</sequence>

</complexType>

When other platforms receive the Flight object, they use this description to map datatypes to property names.The struct and query ColdFusion data types map to theirown complexType depending on the contents of the variable.The data type mappingsare defined in Table 23.1.

Table 23.1 ColdFusion WSDL Type Mappings

ColdFusion Type WSDL Type

string xsd:string or SOAP-ENC:string

numeric SOAP-ENC:double

29 0672324628 CH23 6/8/05 11:11 AM Page 310

Page 334: ColdFusion MX Developer's Cookbook (Developer's Library)

31123.6. Deploying a Web Service

date xsd:dateTime

boolean SOAP-ENC:boolean

array SOAP-ENC:array

binary xsd:base64Binary

struct complexType

query complexType

23.5. Deploying a Web ServiceYou want to deploy a Web service on a ColdFusion application server.

TechniqueAdd ?wsdl to the end of the URL pointing to a CFC to generate a WSDL file.

<cfobject webservice=”http://localhost/DogService.cfc?wsdl” name=”dog”>

<cfoutput>#dog.getDogYears(8)#</cfoutput>

CommentsDeploying Web services in ColdFusion is very simple.The WSDL can be automaticallygenerated by appending ?wsdl to the end of a URL pointing to the Web service CFC.

Sometimes it makes sense to modify the WSDL generated by ColdFusion to usestronger typing. For instance, you might want to change SOAP-ENC:double to SOAP-ENC:integer if your Web service doesn’t use decimal points.You might alsowant to add typing to an array; ColdFusion arrays do not require that all elements be ofthe same type, yet many languages do. Changes to the WSDL can increase the perform-ance, and possibly the interoperability, when communicating with other languages.

NoteIf you modify the WSDL generated by ColdFusion, it is up to your application to ensure that the types

returned from your application meet the specifications defined in the WSDL. WSDL is a contract that the

Web service must adhere to.

Table 23.1 Continued

ColdFusion Type WSDL Type

29 0672324628 CH23 6/8/05 11:11 AM Page 311

Page 335: ColdFusion MX Developer's Cookbook (Developer's Library)

312 CHAPTER 23 Web Services

23.6. Invoking a Web Service with .NETYou want to call a Web service written in ColdFusion with the .NET platform.

TechniqueUse Visual Studio .NET.Here is getDogYears.aspx:

<%@ Page language=”c#” Codebehind=”getDogYears.aspx.cs”

AutoEventWireup=”false”

Inherits=”DogServiceClient.getDogYears” %>

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN” >

<HTML>

<HEAD>

<title>Dog Service C# Client</title>

</HEAD>

<body>

<h1>Dog Service C# Client</h1>

<form id=”Form1” method=”post” runat=”server”>

Enter a value in person years: <asp:TextBox id=TextBox1 runat=”server”/>

<INPUT id=Submit1 type=submit value=Submit name=Submit1 runat=”server”/>

</form>

<%if (dogYears > 0) {%>

<%=personYears%> person years equals <%=dogYears%> dog years

<% }%>

</body>

</HTML>

Here is getDogYears.aspx.cs:

using System;

using System.Web.UI.WebControls;

using System.Web.UI.HtmlControls;

namespace DogServiceClient

{

/// <summary>

/// consumes the getDogYears Web Service

/// </summary>

public class getDogYears : System.Web.UI.Page

{

protected HtmlInputButton Submit1;

protected TextBox TextBox1;

protected double dogYears = 0;

protected double personYears = 0;

private void Page_Load(object sender, System.EventArgs e) {}

29 0672324628 CH23 6/8/05 11:11 AM Page 312

Page 336: ColdFusion MX Developer's Cookbook (Developer's Library)

31323.6. Invoking a Web Service with .NET

#region Web Form Designer generated code

override protected void OnInit(EventArgs e)

{

InitializeComponent();

base.OnInit(e);

}

/// <summary>

/// Required method for Designer support - do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InitializeComponent()

{

this.Submit1.ServerClick += newSystem.EventHandler(this.Submit1_ServerClick);

this.Load += new System.EventHandler(this.Page_Load);

}

#endregion

private void Submit1_ServerClick(object sender, System.EventArgs e)

{

personYears = double.Parse(TextBox1.Text);

localhost.DogServiceService svc = new localhost.DogServiceService();

dogYears = svc.getDogYears(personYears);

}

}

}

CommentsInvoking a ColdFusion Web service in the .NET environment is a relatively simpleprocess when using Microsoft Visual Studio .NET.This example invokes theDogService.cfcWeb service (defined in section 3) from a .NET Web application.

The first step in accessing a Web service is to add a Web Reference to your VisualStudio project. Do this by right-clicking References in the Solution Explorer, and select-ing Add Web Reference.A dialog box prompts you for the address to the Web service. Inthis case, you use http://localhost:8500/DogService.cfc?wsdl, which is thelocation of the WSDL file describing the DogService.Visual Studio generates a stubobject from the WSDL called DogServiceService, in the DogServiceClient.localhost namespace shown next.

Here is Web References\localhost\Reference.cs:

namespace DogServiceClient.localhost {

using System.Diagnostics;

using System.Xml.Serialization;

using System;

using System.Web.Services.Protocols;

using System.ComponentModel;

29 0672324628 CH23 6/8/05 11:11 AM Page 313

Page 337: ColdFusion MX Developer's Cookbook (Developer's Library)

314 CHAPTER 23 Web Services

using System.Web.Services;

[System.Diagnostics.DebuggerStepThroughAttribute()]

[System.ComponentModel.DesignerCategoryAttribute(“code”)]

[System.Web.Services.WebServiceBindingAttribute(

Name=”DogService.cfcSoapBinding”,

Namespace=”http://DefaultNamespace”)]

public class DogServiceService :

System.Web.Services.Protocols.SoapHttpClientProtocol

{

public DogServiceService() {

this.Url = “http://localhost:8500/DogService.cfc”;

}

[System.Web.Services.Protocols.SoapRpcMethodAttribute(“”,

RequestNamespace=”http://DefaultNamespace”,

ResponseNamespace=”http://DefaultNamespace”)]

[return: System.Xml.Serialization.SoapElementAttribute(“return”)]

public System.Double getDogYears(System.Double years)

{

object[] results = this.Invoke(“getDogYears”,

new object[] {years});

return ((System.Double)(results[0]));

}

public System.IAsyncResult BegingetDogYears(System.Double years,

System.AsyncCallback callback, object asyncState)

{

return this.BeginInvoke(“getDogYears”,

new object[] {years}, callback, asyncState);

}

public System.Double EndgetDogYears(System.IAsyncResult asyncResult)

{

object[] results = this.EndInvoke(asyncResult);

return ((System.Double)(results[0]));

}

}

}

In the codebehind file, getDogYears.aspx.cs, the DogServiceService class isinstantiated and the getDogYears method is called using the instance reference—thevariable svc.The result of the getDogYears method is stored in the variabledogYears.The value of dogYears, if greater than zero, is displayed in thegetDogYears.aspx page.

29 0672324628 CH23 6/8/05 11:11 AM Page 314

Page 338: ColdFusion MX Developer's Cookbook (Developer's Library)

31523.7. Invoking a Web Service with Java

23.7. Invoking a Web Service with JavaYou want to call a Web service written in ColdFusion with Java.

TechniqueUse the Apache AXIS WSDL2Java tool to create a Java stub, and then use the stub toinvoke the remote method.

import dogservice.*;

public class DogServiceClient

{

public static final void main(String[] args)

throws Exception

{

Double humanYears = new Double(8);

Double dogYears = null;

dogservice.DogService binding;

binding =

new dogservice.DogServiceServiceLocator().getDogServiceCfc();

dogYears = binding.getDogYears(humanYears);

System.out.println(“Response from DogService = “ + dogYears);

}

}

CommentsApache Axis is an open source project for implementing and invoking Web servicesusing SOAP with Java. Macromedia is a contributor to the Axis project, and ColdFusionMX’s Web services infrastructure is built with Axis.

This example uses DogService.cfc defined in section 3 and requires Apache Axis.You can download Axis at xml.apache.org/axis/; these examples were created withAxis version 1.0.

The easiest way to invoke a Web service in Java using Axis is with the WSDL2Javautility that comes with Axis.You can run the WSDL2Java tool from your command lineas follows:

java org.apache.axis.wsdl.Wsdl2Java http://x/y.wsdl

29 0672324628 CH23 6/8/05 11:11 AM Page 315

Page 339: ColdFusion MX Developer's Cookbook (Developer's Library)

316 CHAPTER 23 Web Services

The tool can also run via an Apache Ant script.Ant is a build tool for Java (download itat ant.apache.org).The following segment of code runs WSDL2Java within an Anttarget:

<taskdef name=”wsdl2java”

classname=”org.apache.axis.tools.ant.wsdl.Wsdl2javaAntTask”/>

<wsdl2java url=”http://localhost:8500/DogService.cfc?wsdl”

output=”${src}”

deployscope=”session”

noimports=”no”

verbose=”no”

testcase=”no”>

<mapping namespace=”http://DefaultNamespace” package=”dogservice”/>

</wsdl2java>

Both methods of running the WSDL2Java tool require the contents of the Axis’s libdirectory, and a JAXP compliant XML parser to be included in the Java classpath.When WSDL2Java executes, it generates several Java source files that can be used toinvoke the Web service.The two files you will use directly are the DogServiceinterface and the DogServiceLocator class.The DogService interface simply definesthe structure of the public methods in your Web service.The interface that Axis gener-ates is as follows:

public interface DogService

extends java.rmi.Remote

{

public java.lang.Double getDogYears(java.lang.Double years)

throws java.rmi.RemoteException,

dogservice.CFCInvocationException;

}

The getDogServiceCfc method in the DogServiceLocator class instantiates a stubclass that implements the DogService interface.

29 0672324628 CH23 6/8/05 11:11 AM Page 316

Page 340: ColdFusion MX Developer's Cookbook (Developer's Library)

24J2EE Interoperability

24.0. IntroductionFor years, ColdFusion thrived as a Web application server, despite the momentum thatMicrosoft’s ASP and Sun’s Servlet/JSP competitive technologies were gaining.ColdFusion’s tag-based syntax made it a favorite among less technical Web designers. Inorder to secure ColdFusion’s long-term future, Macromedia has embraced Sun’s J2EEsuite of standards. Macromedia’s JRun Server is a J2EE application server and, with theMX release, the ColdFusion Server is now a J2EE application that can run on a varietyof J2EE-certified application servers.

The ColdFusion interpreter has been reengineered as a collection of Java Servlets.Thus, all ColdFusion MX applications are J2EE applications, albeit indirectly.This archi-tectural decision opens entirely new Java integration possibilities to ColdFusion pro-grammers. ColdFusion MX provides for end-to-end integration with J2EE JSPs andServlets. Servlets and JSPs can access ColdFusion session and application state and viceversa. In addition, ColdFusion pages can include JSPs and Servlets or forward processingcontrol to them. In addition, ColdFusion MX offers tighter integration with business-tier components, such as Enterprise Java Beans.

This chapter reviews the different techniques you can use to utilize J2EE componentswithin your ColdFusion application. It covers how to access JSPs and Servlets, how toshare application state with J2EE components, and how to access Enterprise Java Beans.

30 0672324628 CH24 6/8/05 11:27 AM Page 317

Page 341: ColdFusion MX Developer's Cookbook (Developer's Library)

318 Chapter 24 J2EE Interoperability

24.1. Redirecting to a Servlet or JSPYou want to forward the ColdFusion request to a Java Servlet or JSP.

TechniqueUse the following CFML code fragment to perform a server-side forward to a JSP orServlet.

<cfscript>

GetPageContext().forward(“date.jsp”);

</cfscript>

CommentsThe GetPageContext() function is a new addition to the CFML language. It providesaccess to the ColdFusion MX PageContext object, allowing you to see and manipulatepage attributes and the request and response Servlet objects.

The MX PageContext object wraps the Java PageContext object and exposes twofunctions for you to use: forward() and include(). Use the forward() function(shown in the previous technique) to forward the processing control to a Servlet or JSPdeployed on the underlying J2EE application server.

You can add JSPs to the standalone version of ColdFusion MX by simply addingthem to your ColdFusion project. Servlets must be declared in the web.xml file underthe WEB-INF folder in the ColdFusion MX wwwroot folder. Unpacked Servlet classesmust be added to the CFusionMX/wwwroot/WEB-INF/classes folder.Alternatively,JAR’ed Servlet libraries can be placed in the CFusionMX/wwwroot/WEB-INF/libfolder.You must use one of the previous methods to deploy your Servlet classes beforeyou can access them in your ColdFusion application.

24.2. Including a Servlet or JSPYou want to include a Java Servlet or JSP in the context of your ColdFusionpage.

TechniqueUse the following CFML code fragment to perform a server-side include of a JSP orServlet.

Including a jsp...

<cfscript>

GetPageContext().include(“date.jsp”);

</cfscript>

30 0672324628 CH24 6/8/05 11:27 AM Page 318

Page 342: ColdFusion MX Developer's Cookbook (Developer's Library)

31924.3. Accessing ColdFusion Pages from Servlets and JSPs

CommentsLike the <cfinclude> tag, the MX PageContext include() function can be usedto include the output of a Servlet or JSP in a CFML page.This technique uses the func-tion to include the output of the date.jsp JSP page.

24.3. Accessing ColdFusion Pages fromServlets and JSPs

You want to access a ColdFusion page from a Servlet or JSP.

Techniquefactorial.cfm:

<cfparam name=”num”>

<cfset result = 1>

<cfloop from=”2” to=”#num#” index=”i”>

<cfset result = result * i>

</cfloop>

<cfoutput>#num#! = #result#</cfoutput>

include.jsp:

<jsp:include page=”factorial.cfm”>

<jsp:param name=”num” value=”10”/>

</jsp:include>

CommentsColdFusion’s Servlet/JSP integration is bi-directional.This means that you can include(or forward to) a ColdFusion page directly from a Servlet or JSP.The technique used toaccess a CFML page from a Servlet or JSP is identical to the one used to access anotherServlet or JSP.This technique uses the standard <jsp:include/> JSP tag to includethe results of a ColdFusion page called factorial.cfm. Note that you can use the<jsp:param/> tag to set any parameters the ColdFusion page needs in order to operate.

30 0672324628 CH24 6/8/05 11:27 AM Page 319

Page 343: ColdFusion MX Developer's Cookbook (Developer's Library)

320 Chapter 24 J2EE Interoperability

24.4. Sharing Data Between ColdFusion andServlets/JSPs

You want to share common application data with JSPs and Servlets.

TechniqueSetvars.cfm:

<cfapplication name=”cfsession” sessionmanagement=”yes”>

<cfset Request.requestvar = “Request Variable”><cfset Session.sessionvar = “Session Variable”><cfset Application.applicationvar = “Application Variable”>

<cfscript>GetPageContext().include(“/PrintVars”);

</cfscript>

PrintVars.java:

package org.acme;

import java.io.IOException;import java.io.PrintWriter;import java.util.*;import javax.Servlet.ServletException;import javax.Servlet.http.HttpServlet;import javax.Servlet.http.HttpServletRequest;import javax.Servlet.http.HttpServletResponse;

public class PrintVars extends HttpServlet{

protected void processRequest(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException

{// Get POST and GET parametersPrintWriter out = response.getWriter();out.print(“<b>Page Parameters:</b><br>”);Enumeration params = request.getParameterNames();while (params.hasMoreElements()){

String name = (String)params.nextElement();String value = (String)request.getParameter(name);out.print(name+” = “+value+”<br/>”);

}

// Get Request Attributesout.print(“<p>”);

30 0672324628 CH24 6/8/05 11:27 AM Page 320

Page 344: ColdFusion MX Developer's Cookbook (Developer's Library)

32124.4. Sharing Data Between ColdFusion and Servlets/JSPs

out.print(“<b>Page Attributes:</b><br>”);Enumeration attrs = request.getAttributeNames();while (attrs.hasMoreElements()){

String name = (String)attrs.nextElement();String value = (String)request.getAttribute(name);out.print(name+” = “+value+”<br/>”);

}

// Get Session Variablesout.print(“<p>”);out.print(“<b>CF Session Variables:</b><br>”);Map sessionVars = (Map)request.getSession().getAttribute(“cfsession”);Set sessionAttrs = sessionVars.keySet();for (Iterator i = sessionAttrs.iterator(); i.hasNext();){

String name = (String)i.next();String value = sessionVars.get(name).toString();out.print(name+” = “+value+”<br/>”);

}}

protected void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException

{processRequest(request,response);

}

protected void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException

{processRequest(request,response);

} }

CommentsAn exciting new feature in ColdFusion MX is the capability to share application andsession state among ColdFusion pages and J2EE Servlets and JSPs.The storage mecha-nism for ColdFusion application state has been redesigned in MX to utilize the standardJ2EE request parameters, request attributes, and HTTP session objects.

This allows you to mix ColdFusion pages with Servlets and JSPs in a single applica-tion while maintaining consistent session state.Thus, you can draw upon each of theWeb page development technologies when the need arises. For example, you might useColdFusion to rapidly assemble a front-end that gathers information to be passed to aServlet-driven back-end business method.

30 0672324628 CH24 6/8/05 11:27 AM Page 321

Page 345: ColdFusion MX Developer's Cookbook (Developer's Library)

322 Chapter 24 J2EE Interoperability

In the technique shown here, ColdFusion is used to populate an assortment of sessionand request variables, which is subsequently inspected by a Java Servlet.The exampleuses the expression GetPageContext().include(“/PrintVars”) to include thePrintVars Servlet that prints the application state.The PrintVars Servlet logic isdivided into three sections that handle printing the request parameters, request attributes,and session variables.

Request parameters, such as URL and form variables, are available in the Parameterscope of the request object. Individual parameters can be accessed by calling therequest.getParameter(parameterName) function. Likewise, you can extractColdFusion request variables (such as the one created with the CFML statement<cfset request.requestVar = “Request Variable”>) with theRequest.getAttribute(attributeName) function.

ColdFusion session variables, however, are handled slightly differently.The ColdFusionruntime engine keeps all session state in a single Servlet session variable matching thename of the ColdFusion application.This example assigned a name to the CFML pageand created a session scope for it by using the <cfapplication> tag:<cfapplication name=”cfsession” sessionmanagement=”yes”>. Behind thescenes, ColdFusion created a Java map to store session state and added it to the Servletsession scope under the name cfsession.

This Servlet retrieves the ColdFusion session state block with the expression: MapsessionVars = (Map)request.getSession().getAttribute(“cfsession”).Individual CFML session variables can thenceforth be accessed by their names. Forexample, the Servlet can get the value of the sessionvar ColdFusion session variableby using the expression sessionVars.get(“sessionvar”).

24.5. Accessing Enterprise Java BeansYou want to access an Enterprise Java Bean from your ColdFusion template.

TechniqueMath.java:

package org.acme.beans.math;

import java.rmi.RemoteException;

import javax.ejb.EJBObject;

public interface Math extends EJBObject

{

public int add(int a, int b) throws RemoteException;

public double add(double a, double b) throws RemoteException;

public int factorial(int number) throws RemoteException;

}

30 0672324628 CH24 6/8/05 11:27 AM Page 322

Page 346: ColdFusion MX Developer's Cookbook (Developer's Library)

32324.5. Accessing Enterprise Java Beans

MathHome.java:

package org.acme.beans.math;

import java.rmi.RemoteException;

import javax.ejb.CreateException;

import javax.ejb.EJBHome;

public interface MathHome extends EJBHome

{

public Math create() throws CreateException, RemoteException;

}

MathBean.java:

package org.acme.beans.math;

import javax.ejb.CreateException;

import javax.ejb.SessionBean;

import javax.ejb.SessionContext;

public class MathBean implements SessionBean

{

transient protected SessionContext ctx;

public void ejbCreate() throws CreateException {}

public void ejbRemove() {}

public void ejbActivate() {}

public void ejbPassivate() {}

public void setSessionContext(SessionContext ctx) {this.ctx = ctx;}

public int add(int a, int b)

{

return a + b;

}

public double add(double a, double b)

{

return a + b;

}

public int factorial(int number)

{

int result = 1;

for (int i = 2; i <= number; i++)

{

result *= i;

30 0672324628 CH24 6/8/05 11:27 AM Page 323

Page 347: ColdFusion MX Developer's Cookbook (Developer's Library)

324 Chapter 24 J2EE Interoperability

}

return result;

}

}

CallEJB.cfm:

<cfscript>

ctx = CreateObject(“java”,”javax.naming.Context”);

props = CreateObject(“java”,”java.util.Properties”);

props.init();

props.put(ctx.INITIAL_CONTEXT_FACTORY, “jrun.naming.JRunContextFactory”);

props.put(ctx.PROVIDER_URL, “localhost:2908”);

initContext = CreateObject(“java”,javax.naming.InitialContext);

initContext.init(props);

mathHome = initContext.lookup(“MathBean”);

mathBean = mathHome.create();

result = mathBean.factorial(10);

WriteOutput(“Result = “&result);

</cfscript>

CommentsSun’s Enterprise Java Beans specification has matured over the years and has seen a cor-responding growth in its adoption.The technology, which has undergone two majorreleases, is an attractive tool to model complex business processes.A J2EE applicationserver, such as Macromedia’s JRun Server, hosts your EJB business components and pro-vides a wealth of infrastructure that you, the component author, can draw upon. Supportfor transactions, clustering, security, and database persistence are just a few of the power-ful features mandated by the EJB specification.

EJB-based components are accessible to a wide range of clients, from rich desktopapplications to thin Web-based clients, including ColdFusion. ColdFusion template inte-gration with EJB components is a more efficient process now that the ColdFusion inter-preter is, itself, a Java process. One benefit of this implementation is that a ColdFusionclient can access an EJB’s local interface. EJB local interfaces are optimized for in-processcalls and avoid the overhead imposed by their RMI-based remote counterparts.

This example creates a small stateless session EJB that exposes methods for adding dif-ferent types of numbers and finding the factorial of an integer.Although a detailedexplanation of the mechanics of an EJB is beyond the scope of this chapter, a briefoverview of the classes involved is in order. Math.java declares the interface that theapplication server will expose to remote clients once this EJB has been deployed.MathHome.java is also an interface that declares a single method, create(), thatclients can use to obtain an instance of a Math EJB. Finally, the MathBean.java

30 0672324628 CH24 6/8/05 11:27 AM Page 324

Page 348: ColdFusion MX Developer's Cookbook (Developer's Library)

32524.5. Accessing Enterprise Java Beans

abstract class implements the bean’s business logic.The class also contains the requiredEJB house-keeping methods (for example, ejbCreate()).These three files are placedinto a single JAR file along with an XML deployment descriptor that describes thecomponent to the application server.

Once deployed, the MathBean EJB is available to its clients.This technique creates aColdFusion template that looks up the bean and calls one of its methods.The lookupprocess requires several steps and a handful of classes, so it uses a <cfscript> block toisolate this logic. First, EJB clients must use the Java Naming Directory Interface (JNDI)to locate an instance of the bean’s home interface.The code is as follows:

ctx = CreateObject(“java”,”javax.naming.Context”);

props = CreateObject(“java”,”java.util.Properties”);

props.init();

props.put(ctx.INITIAL_CONTEXT_FACTORY, “jrun.naming.JRunContextFactory”);

props.put(ctx.PROVIDER_URL, “localhost:2908”);

initContext = CreateObject(“java”,javax.naming.InitialContext);

This code creates an instance of a JNDI InitialContext and initializes it with aProperties object.The context object must be initialized with a CONTEXT_FACTORY(usually application server-dependent) and a PROVIDER_URL (the Web address and portof the application server’s Java Naming Provider [JNP] service). Once initialized, you canuse the JNDI context object to look up your bean’s home interface.The bean’s name isspecified in its deployment descriptor.The statement mathHome =initContext.lookup(“MathBean”) looks up the bean and returns an instance of itshome interface.

NoteEJB clients never talk directly to a bean’s business logic. The Home and Remote objects that an EJB client

uses are generated by the EJB’s container. This level of indirection is necessary for the application server to

implement the caching, transactions, and other services required by the specification.

Finally, you use the bean’s home interface to create an actual instance of the bean to callits factorial() method:

mathBean = mathHome.create();

result = mathBean.factorial(10);

WriteOutput(“Result = “&result);

When run, the example should output the following message:

Result = 3628800

This seems like a lot of work for finding a simple factorial and it is. If you plan on usingEJBs in your ColdFusion applications, you should create a custom tag to automate the

30 0672324628 CH24 6/8/05 11:27 AM Page 325

Page 349: ColdFusion MX Developer's Cookbook (Developer's Library)

326 Chapter 24 J2EE Interoperability

process of looking up the bean’s home interface and calling the create() method.Thiswill save you time in debugging error-prone code and will also make your applicationmore flexible if you ever change the application server’s implementation or the host IPaddress.

30 0672324628 CH24 6/8/05 11:27 AM Page 326

Page 350: ColdFusion MX Developer's Cookbook (Developer's Library)

VIAppendixes

A Online ColdFusion Resources

B Security

C Migrating from ColdFusion 5 to CFMX

D Converting Between Tags and Scripting

31 0672324628 Part 06 6/8/05 11:11 AM Page 327

Page 351: ColdFusion MX Developer's Cookbook (Developer's Library)

31 0672324628 Part 06 6/8/05 11:11 AM Page 328

Page 352: ColdFusion MX Developer's Cookbook (Developer's Library)

AOnline ColdFusion Resources

Online resources are a great way to enhance your skills.This appendix includes Websites that provide resources in the form of articles, discussion forums, mailing lists, tutori-als, code sharing, and other forms.

ColdFusion Web SitesCF Bug Hunthttp://www.cfbughunt.org/

Online public bug database for ColdFusion.CF Bookmarkhttp://www.cfbookmark.com/

A listing of links related to ColdFusion.CFCustomTags.comhttp://www.cfcustomtags.com/

Includes a tag gallery, forums, and tutorials.CFCZonehttp://www.cfczone.org/

Includes a CFC gallery, mailing list, and frequently asked questions (FAQs).CFDEVhttp://www.cfdev.com/

Includes code samples, articles, tags, links, and products.CFDEVXhttp://www.cfdevx.com/

A directory of ColdFusion links.CF FAQhttp://www.cffaq.com/

Frequently asked questions related to ColdFusion.

32 0672324628 AppA 6/8/05 11:11 AM Page 329

Page 353: ColdFusion MX Developer's Cookbook (Developer's Library)

330 Appendix A Online ColdFusion Resources

CFHub.comhttp://www.cfhub.com/

Includes articles, tutorials, forums, and other resources.CFMCentralhttp://www.cfmcentral.com/

Includes forums, tags, jobs, tips, resources, products, services, and events.ColdFusion Developers Journalhttp://www.sys-con.com/coldfusion/

Includes articles, a mailing list, and forums.ColdFusion FAQhttp://www.thenetprofits.co.uk/coldfusion/faq/

Frequently asked questions and answers about ColdFusion.CFLib.orghttp://www.cflib.org/

A library of free user-defined functions and resources.Defusionhttp://www.defusion.com/

Includes news, articles, resources, and forums.DEVMXhttp://www.devmx.com/

Includes tutorials, forums, articles, mailing list, and other resources related to MacromediaMX products.EasyCFM.comhttp://www.easycfm.com/

Includes tutorials, references, forums, and links.Full as a Googhttp://www.fullasagoog.com/

Aggregator for Macromedia-related blogs.Fusion Authorityhttp://www.fusionauthority.com/

Includes weekly ColdFusion news, tips, and resources.House of Fusionhttp://www.houseoffusion.com/

Includes several mailing lists, articles, and community resources.Live Documentationhttp://livedocs.macromedia.com/

Online ColdFusion documentation that allows developers to post comments, clarifica-tions, and corrections.Macromedia Designer and Developer Centerhttp://www.macromedia.com/desdev/

Includes articles for designers and developers using Macromedia products.

32 0672324628 AppA 6/8/05 11:11 AM Page 330

Page 354: ColdFusion MX Developer's Cookbook (Developer's Library)

331XML Web Sites

Macromedia Online Forumshttp://webforums.macromedia.com/

Includes discussion forums for Macromedia products.Macromedia ColdFusion Support Centerhttp://www.macromedia.com/support/coldfusion/

Search technotes and knowledge base articles.Open Directory ColdFusion Categoryhttp://dmoz.org/Computers/Programming/Internet/ColdFusion/

The Open Directory Project’s listing of ColdFusion links.Secret Agentshttp://www.secretagents.com/

Includes tutorials, free code, and articles.

Java Web SitesThe Apache Jakarta Projecthttp://jakarta.apache.org

Open Source Java software. Includes a JSP custom tag libraries, JSP and Servlet engine,and several other projects.JSP Tagshttp://www.jsptags.com/

A listing of JSP custom tag libraries.JSP Resource Indexhttp://www.jspin.com/

A categorized directory of JSP resources.Open Directory Server-Side Java Categoryhttp://dmoz.org/Computers/Programming/Languages/Java/Server-Side/

A directory of server-side Java Web sites, including JSP and Servlets.Sun Microsystems Java Sitehttp://java.sun.com/

Includes tutorials and articles for learning Java, as well as the tools needed to develop andrun Java applications.

XML Web SitesThe Apache XML Projecthttp://xml.apache.org/

Open Source software relating to XML. Includes the AXIS project, which is the underbelly of the Web services implementation in ColdFusion MX.Open WDDXhttp://www.openwddx.org/

The home of the WDDX project. Includes WDDX development kits for several languages.

32 0672324628 AppA 6/8/05 11:11 AM Page 331

Page 355: ColdFusion MX Developer's Cookbook (Developer's Library)

332 Appendix A Online ColdFusion Resources

Xmethodshttp://www.xmethods.com

A listing of Web services, many of which are free.XML.comhttp://www.xml.com/

Articles and resources for working with XML technologies.

Other Useful Web SitesEvolthttp://www.evolt.org/

Includes articles, mailing lists, tips, and links.Jakob Nielsen’s Web Sitehttp://www.useit.com/

Includes usability and Web design articles.Section 508 Accessibility Informationhttp://www.section508.gov/

Information for building Web sites accessible to disabled visitors.

32 0672324628 AppA 6/8/05 11:11 AM Page 332

Page 356: ColdFusion MX Developer's Cookbook (Developer's Library)

BSecurity

An ever increasing amount of sensitive and private information is accessible to thepublic over the Internet.Awareness of best practices, as well as the common routesattackers take are necessities for Internet developers.The cost of applying security meas-ures is orders of magnitude smaller than the potential cost of a security breach.

This appendix covers some common security problems, but is by no means a com-plete list. Security is a constantly changing beast; to keep up-to-date, visit the Web sitesin the “Security Resources” section of this appendix.

Session HijackingWhen you use session or client variables in ColdFusion, two variables are set—CFID andCFTOKEN.The variables are stored as cookies on the client’s computer, or passed in theURL. CFID and CFTOKEN are often passed through the URL to allow clients withcookies disabled to maintain state.

Security concerns arise when someone has access to the values of CFID and CFTO-KEN. By providing a CFID and CFTOKEN that matches an active session, you can “hijack”or “spoof” the session (bypassing the Web site’s login mechanism).

Unfortunately, there are several ways an attacker can obtain session identificationnumbers.The attacker can use a packet sniffer to gather URLs and session identifiersfrom the traffic on the network.The session IDs can also be obtained by looking in thebrowser history (if the user didn’t log out). If the session IDs aren’t large and complexenough, hackers can even guess them.

By following some best practices, as follows, you can minimize the potential possibili-ty of session hijacking:

n Use SSL (Secure Socket Layer, HTTPS) for session-enabled sites. SSL encrypts alltransmission of cookies and URLs, thus making it nearly impossible for an attackerto sniff your session identifiers.

n Use CFID and CFTOKEN in the URL only as a last resort. Because URLs are oftencached, or stored by the browser, an attacker can possibly retrieve those values. Use

33 0672324628 AppB 6/8/05 11:11 AM Page 333

Page 357: ColdFusion MX Developer's Cookbook (Developer's Library)

334 Appendix B Security

CFIDs and CFTOKENs only when you’re required to use a session when cookies arenot enabled.You can use the URLSessionFormat function with J2EE sessions toprint the session ID only when cookies are disabled.

n Use a UUID for CFTOKEN.You enable this setting in ColdFusion Administrator. Byusing a UUID, it is much more difficult to guess the CFTOKEN (it uses a much larg-er number). UUIDs are also guaranteed to be unique on your server. ColdFusionuses a random number, which could in some cases cause session crossover.You canalternatively use J2EE sessions to solve the same problems.

Another approach that isn’t necessarily a best practice because it can cause problems withsome ISPs is to store the client’s IP address in a session variable.Then, at each pagerequest, you verify that the client’s IP address is the same as the address stored in the ses-sion variable. If the addresses do not match, you force another login.This can causeproblems for ISPs that change IP addresses frequently.This approach also doesn’t protectusers on a shared IP address (proxies).

URL Injection HackingBy appending special characters to a URL, attackers can run SQL commands of theirchoice on some database platforms.The most common (and most dangerous) form ofthis attack takes place on databases that allow multiple statements to be executed in onequery (typically by separating SQL statements with a semicolon). Consider the followingquery:

<cfquery ...>

SELECT column FROM table WHERE id = #url.id#

</cfquery>

Under normal circumstances, the value of url.id would be some integer. However,because the value of the variable is in the hands of the attackers, they could pass a valuelike id=123;delete FROM table, which would delete all records from your table.

The best defense to URL injection hacking is to use the <cfqueryparam> tag.Thefollowing example is immune from such an attack:

<cfquery ...>

SELECT column FROM table

WHERE id = <cfqueryparam cfsqltype=”CF_SQL_INTEGER” value=”#url.id#”>

</cfquery>

The <cfqueryparam> tag performs data-type checking, and also escapes special charac-ters in the value passed. More information about <cfqueryparam> is available inChapter 14,“Structured Query Language (SQL).”

Besides using the <cfqueryparam> tag as a general best practice, you should alwaysensure that ColdFusion doesn’t have any excess permission to the database. Be restrictive

33 0672324628 AppB 6/8/05 11:11 AM Page 334

Page 358: ColdFusion MX Developer's Cookbook (Developer's Library)

335Denial of Service Attacks

with the DELETE and DROP permissions.Also ensure that the database system stored pro-cedures are locked down.

Another solution to this problem is to use stored procedures. Stored procedures arecovered in detail in Chapter 15,“Stored Procedures.”

Not all databases allow multiple SQL statements to execute. Microsoft SQL Serverand Postgres are two that do allow multiple statements.

In addition to multiple statement execution, it is sometimes possible to perform othermalicious operations when unchecked variables exist in the SQL query.

Attackers using this technique can’t do any harm without knowing, or guessing, thedatabase structure. Be sure that debugging information and error message details areturned off on production servers.Although this is a best practice, it doesn’t provide anyreal security from attacks. It is very easy to guess monikers like database table names(products, users, orders, and so on).

File UploadingGiving users the capability to upload files can be very dangerous without properly secur-ing the code and the upload directory.

The <cffile> tag, used to upload files from a form, has an attribute called accept.This attribute is used to specify allowable MIME types.The accept attribute shouldalways be used, but it may provide a false sense of security.The MIME type it uses is sentfrom the client. Hackers can easily send a .CFM file claiming to have a MIME type ofimage/gif (or any other MIME type). Because of this dangerous fact, you shouldcheck the file extension of the uploaded file to ensure that it is expected.

<cfif cffile.ServerFileExt IS NOT “gif”>

<cffile action=”delete” file=”#cffile.ServerDirectory#\#cffile.serverfile#”>

Sorry incorrect file type.

<cfabort>

</cfif>

You can use the cffile.ServerFileExt attribute to determine whether the fileuploaded has the correct extension, and if not, delete it.

It’s best to ensure that the directory that files are uploaded to is not under the Webroot (if possible). If files must be uploaded to the Web root, the Web server should notallow execution of scripts (such as .CFM files).

Denial of Service AttacksDenial of service, or DOS, attacks are categorized by attempts to overload and crash aserver by utilizing as many resources as possible. Distributed DOSs involve a multipleattack by several machines, all trying to overload a more powerful server. Such attacks arevery difficult, and sometimes impossible, to prevent.

33 0672324628 AppB 6/8/05 11:11 AM Page 335

Page 359: ColdFusion MX Developer's Cookbook (Developer's Library)

336 Appendix B Security

The key preventive measure for such attacks is to minimize the relationship of input topage loading time.An exaggerated example of a scenario to avoid follows:

<cfloop from=”1” to=”#url.loop#” index=”i”>

<!--- do something --->

</cfloop>

In this example, anyone can control the number of loops the application performs.A more practical example might include a page that performs several manipulations

and transformations on an input string.To prevent problems, check the size of the stringagainst its upper limit before performing the costly manipulations.

Cross Site ScriptingCross site scripting (or sometimes referred to as XSS, or CSS, but not to be confusedwith cascading style sheets) attacks involve injecting client side code (HTML, JavaScript,VBScript,ActiveX, Flash, and so on) through a variable passed by the client.The variableis typically from a form submission or a URL query string. For example, the followingcode has a cross site scripting vulnerability.

Consider the following form:

<form method=”post” action=”formActionPage.cfm”>

<textarea name=”variable”></textarea>

<input type=”submit” value=”submit”>

</form>

And the following form action page:

<cfif IsDefined(“form.variable”)>

<cfoutput>

#form.variable#

</cfoutput>

</cfif>

The form action page is basically a blank slate for a malicious attacker to use. Consideran attacker posting the following:

<script>

alert(document.cookie);

</script>

This code will place the values for all cookies into a Java script alert box.This code isn’tdangerous, but if instead it submitted the cookie information to a malicious Web site,you could be in trouble.

Cookies aren’t the only risk faced by cross site scripting attacks.An attacker mightalso spoof a Web page and get you to enter personal information, thinking that you’reusing a valid Web site. It is very difficult for the average user to know whether they are

33 0672324628 AppB 6/8/05 11:11 AM Page 336

Page 360: ColdFusion MX Developer's Cookbook (Developer's Library)

337Security Resources

under such an attack, because the URL will appear to be valid, and SSL certificates willstill validate. Many other possible scenarios exist as well.

The remedy for CSS scripting attacks is fortunately very simple.TheHTMLEditFormat function will automatically convert < and > characters into &lt; and&gt;, respectively. So instead of the code executing on the client, the code is simply dis-played.To fix the previous form action page, you simply apply the HTMLEditFormatfunction to form.variable before displaying it.

<cfif IsDefined(“form.variable”)>

<cfoutput>

#HTMLEditFormat(form.variable)#

</cfoutput>

</cfif>

Sandbox SecuritySandbox security in ColdFusion MX allows a server administrator to disable tags, data-sources, functions, files, and directories. Sandbox security also lets you disable access toservers and ports.These features can be disabled based on a file pattern such as(c:\inetpub\wwwroot\), called a sandbox.

To set up sandbox security, go to the ColdFusion MX Administrator, and click theSandbox Security link.

Many developers think that the sandbox security setting in ColdFusion MX existsonly for Internet Service Providers (ISP) offering shared hosting environments.However, it can be useful as a last line of defense on any ColdFusion server.

It is a good idea to disable any tags or functions that your application isn’t using,especially those that can harm the system such as <cffile>, <cfdirectory>,<cfexecute>, and <cfregistry>, to name a few.

If your ColdFusion application server is behind a firewall with other servers, it’s also agood idea to use the sandbox server IP restrictions. For instance, if your intranet server isbehind the same firewall as your public Web server, an attacker that has gained access toyour public Web server can use <cfhttp> to access your intranet.

For obvious reasons, sandbox security is also useful on servers that host multipleapplications by multiple users. In order to ensure that users don’t tamper with otheruser’s applications and files, a sandbox security policy must be implemented.

Security ResourcesMicrosoft Security Bulletinhttps://www.microsoft.com/technet/security/bulletin/notify.asp

Sign up for the security newsletter to be notified about potential security flaws inMicrosoft products.

33 0672324628 AppB 6/8/05 11:11 AM Page 337

Page 361: ColdFusion MX Developer's Cookbook (Developer's Library)

338 Appendix B Security

Macromedia Security Zonehttp://www.macromedia.com/security

Any security patches or security bulletins are posted here.You can also sign up for emailalerts.

Windows Updatehttp://windowsupdate.microsoft.com/

Download the latest patches, updates, and security fixes for Windows servers.

The CERT Coordination Centerhttp://www.cert.org/

Includes security best practices, vulnerabilities, and fixes.

SecurityFocus Vulnerability Databasehttp://www.securityfocus.com/corporate/products/vdb

A searchable database containing security vulnerabilities.

33 0672324628 AppB 6/8/05 11:11 AM Page 338

Page 362: ColdFusion MX Developer's Cookbook (Developer's Library)

CMigrating from ColdFusion 5 to

ColdFusion MX

ColdFusion MX represents a drastic change in ColdFusion’s underlying technology.The ColdFusion engine was redesigned from the ground-up as an assembly of Java serv-er-side components, replacing its older native C++ executable architecture.This kind ofchange in architecture from one release to another can often lead to incompatibilities.

Fortunately, the developer team at Macromedia did a good job of maintaining back-wards compatibility for the vast majority of functionality.There are some tags and func-tions, however, that have changed or are no longer supported in ColdFusion MX. Forthis reason, Macromedia included the Compatibility Analyzer and the Settings MigrationWizard to help developers convert their legacy applications to use CFMX.

ColdFusion MX uses a stricter syntax checker than earlier versions of ColdFusion.Pages that once worked correctly, despite incorrect syntax, may now break under theMX parser.

ColdFusion Code Compatibility AnalyzerThe ColdFusion Compatibility Analyzer will assess your CFML application for compati-bility with ColdFusion MX.The analyzer will let you know if your application relies onfeatures in the ColdFusion 5.0 CFML language that have been changed, deprecated, orremoved in ColdFusion MX.The Compatibility Analyzer will also check your applica-tion for syntax errors.

To access the Compatibility Analyzer, log into the ColdFusion administrator and clickthe Code Analyzer link under the Debugging and Logging header.

ColdFusion Settings Migration Wizard Another significant change in the architecture of ColdFusion MX is how it stores itsregistry settings.After installing MX, you should run the Settings Migration Wizard toconvert your ColdFusion 5 settings into MX.

34 0672324628 AppC 6/8/05 11:11 AM Page 339

Page 363: ColdFusion MX Developer's Cookbook (Developer's Library)

340 Appendix C Migrating from ColdFusion 5 to ColdFusion MX

To run the wizard, you must have MX running on the same machine as the instanceof ColdFusion that you are upgrading. Depending on your platform, ColdFusion willprompt you to run the Migration Wizard upon completion of the installation (Windows)or the first time you log into the ColdFusion administrator (UNIX).

Changes to CFML Tags and FunctionsThere are numerous changes to the CFML language in MX.The majority of these aresmall changes in behavior of some of the tags.A small number of tags and functions,however, have been deprecated or removed entirely.The ColdFusion online documenta-tion includes a comprehensive list of all the changes that were made to the CFML lan-guage.

Database Operations ColdFusion MX uses a different database communications API than its predecessors.Older versions of ColdFusion used ODBC and OLE-DB drivers to provide databaseaccess. ColdFusion MX is a Java-based application and uses the Java DatabaseConnectivity (JDBC) API to connect to databases. Because of this, you will need toobtain JDBC drivers from your database vendor or else use the Merant Type 4 driver orthe SQL Link Type 3 driver to connect to ODBC data sources.

ColdFusion MX Query objects now store query columns using their JDBC datatypes, as opposed to earlier versions of ColdFusion, which represented all columns asstrings. ColdFusion MX converts non-string entities to strings by calling the JavatoString() method on the object.This may lead to differences in the display of dates,numbers, and monetary units from database queries.

LocalizationColdFusion MX includes new internationalization support. MX supports new currencyformats and formatting functions.The ColdFusion MX online documentation containsdetailed information on these new internationalization features.

ReferencesYou should always check your ColdFusion release notes before upgrading for version-specific information. Migration notes for ColdFusion MX can be found in theColdFusion documentation at the following address:

/cfdocs/Migrating_ColdFusion_5_Applications/contents.htm

Macromedia has posted a detailed article on migrating to ColdFusion MX on its Website. It can be found at:

http://www.macromedia.com/desdev/mx/coldfusion/articles/migrating.html

34 0672324628 AppC 6/8/05 11:11 AM Page 340

Page 364: ColdFusion MX Developer's Cookbook (Developer's Library)

DConverting Between Tags

and Scripting

Although the CFML tag syntax is most useful for adding dynamic content to other-wise static HTML pages, it can become a bit unwieldy when authoring a large, contigu-ous block of application logic.To this end, CFML scripting was introduced inColdFusion version 4.0. CFML scripting allows you to embed a series of Java-like state-ments and expressions within your ColdFusion template. CFML scripts have the sameaccess to application state as their tag-based counterparts.

The <cfscript> TagCFML scripts are always enclosed within the body of a <cfscript> tag.The<cfscript> tag may contain a valid series of CFScript statements.The values ofCFScript statements are not displayed to the page.You must use the WriteOutput()function to output any information to the resulting Web page.Although scripts are notso great for handling display and formatting, they are the ideal choice for implementinglarge sections of application logic. For example, consider the following switch state-ment implemented using both tags and scripts:

Using tags:

<cfset choice = form.choice>

<cfswitch expression=”#choice#”>

<cfcase value=”0”>

<cfset color=”red”>

</cfcase>

<cfcase value=”1”>

<cfset color=”blue”>

</cfcase>

<cfcase value=”2”>

<cfset color=”yellow”>

35 0672324628 AppD 6/8/05 11:11 AM Page 341

Page 365: ColdFusion MX Developer's Cookbook (Developer's Library)

342 Appendix D Converting Between Tags and Scripting

</cfcase>

<cfcase value=”3”>

<cfset color=”green”>

</cfcase>

<cfdefaultcase>

<cfset color=”purple”>

</cfdefaultcase>

</cfswitch>

Using a script:<cfscript>

choice = form.choice;

switch(choice)

{

case “0”:

color=”red”;

break;

case “1”:

color=”blue”;

break;

case “2”:

color=”yellow”;

break;

case “3”:

color=”green”;

break;

default:

color=”purple”;

break

}

</cfscript>

Scripts make your application logic easier to follow and to maintain. Programmersshould be familiar with script flow-control statements (such as the switch statement), asthey are based on similar statements in the C and Java programming language.

CFML scripts are composed of semicolon-delimited statements. CFML supports thefollowing types of statements: assignment, function call, if-else, switch-case, for,for-in, while, do-while, break, continue, try-catch, function, var, andreturn.The last three statements are used within user-defined functions (covered inChapter 16,“User-Defined Functions”).

Assignment statements are used to assign a value to a variable. For example, the state-ment a = 3; assigns the value 3 to the variable a.A variable may be assigned either aliteral value (such as the number 3) or the result of an expression.An expression is agroup of functions, operators, and literals that, when evaluated, produce a value. In otherwords, an expression is anything that you can use on the right side of a <cfset> tag.For example, the statement a = Rand() * 10; assigns the value of the expressionRand() * 10 to the variable a.

35 0672324628 AppD 6/8/05 11:11 AM Page 342

Page 366: ColdFusion MX Developer's Cookbook (Developer's Library)

343Loops

Function-call statements are used to call a CFML or user-defined function that hasno return value and, thus, cannot be assigned to a variable. For example, the statementWriteOutput(“Hello World”); writes the string “Hello World” to the pageresult.

If-Then StatementsIf-Then-Else statements are very easy to implement in CFScript.The if statementuses the following syntax:

if (expression) statement

where expression is a true/false, or Boolean, expression and statement is either asingle statement or a group of statements enclosed in braces (“{}”). For example, the fol-lowing if statement sets the value of color to “blue” if the variable choice is equalto the number 1:

if (choice eq 1)

{

color = “blue”;

}

Note that the braces in this example are optional because the if statement includes onlyone line.

An if statement may also contain an else statement that executes if the expressionevaluates to false. In such cases, the syntax is:

if (expression) statement else statement

The following example uses the else statement to assign the value “red” to the vari-able color if the value of choice is anything but 1:

if (choice eq 1)

{

color = “blue”;

}

else

{

color = “red”;

}

The CFML script language does not contain an elseif keyword.You must use theelse and if keywords instead.

LoopsYou should consider using CFML scripts to implement looping logic in your CFMLapplication, particularly if your loop does not control any display logic. For example,scripts are an ideal means to initialize a large array with a set of values.

35 0672324628 AppD 6/8/05 11:11 AM Page 343

Page 367: ColdFusion MX Developer's Cookbook (Developer's Library)

344 Appendix D Converting Between Tags and Scripting

The CFML scripting language includes support for the following types of loops: for,for-in, while, and do-while.

The for loop is useful for iterating over a fixed number of items (such as the con-tents of an array).The following for loop prints the contents of an array:

for (i = 1; i <= ArrayLen(myarray); i = i + 1)

{

value = myarray[i];

WriteOutput(“myarray[“&i&”] = “&value&”<br/>”);

}

The for expression contains three separate statements within parentheses.The first state-ment initializes a variable to be used in the loop (such as i = 1;).The second state-ment is a true/false expression that determines whether the body of the loop should beexecuted (such as i <= ArrayLen(myarray)).The body of the loop will execute aslong as the expression evaluates to true.The third statement contains an expression thatis evaluated after each iteration of the loop. It typically contains logic to increment acounter. For example, the expression i = i + 1 increments the counter i by one eachtime through the loop.

The for-in loop is similar to a for loop except that it is explicitly designed to iter-ate over the members of a ColdFusion structure.The syntax is as follows:

for(keyname in structure) statement

For example, the following loop iterates over all of the fields contained in a CFMLstructure called personstruct:

for (fieldname in personstruct)

{

fieldvalue = personstruct[fieldname];

WriteOutput(“personstruct.”&fieldname&” = “&fieldvalue&”<br/>”);

}

While and Do-While loops are simple to use. Both loops simply execute until theirtrue/false expression evaluates to false.The only difference is that While loops evalu-ate the true/false expression before each iteration, whereas Do-While loops check itafterwards. See if you can determine the value of cnt after the execution of both ofthese loops.

cnt = 1;

while (cnt < 10)

{

cnt = cnt + 2;

}

cnt = 1;

do

35 0672324628 AppD 6/8/05 11:11 AM Page 344

Page 368: ColdFusion MX Developer's Cookbook (Developer's Library)

345Switch Statements

{

cnt = cnt + 2;

}

while (cnt < 10)

Sometimes you encounter conditions that require you to bail out of a loop entirely orelse to skip directly to the next iteration of the loop.The break and continue state-ments let you do this. Break will quit the loop entirely, whereas continue will jumpstraight to the top of the loop.The following loop breaks if an array element containsthe value -1.

for (i = 1; i <= ArrayLen(myarray); i = i + 1)

{

value = myarray[i];

if (value eq -1) break;

WriteOutput(“myarray[“&i&”] = “&value&”<br/>”);

}

This loop divides the number 10 by each value in an array unless the value is 0:

for (i = 1; i <= ArrayLen(myarray); i = i + 1)

{

divisor = myarray[i];

if (divisor eq 0) continue;

WriteOutput(10 / divisor);

}

Switch StatementsSwitch statements in CFScript behave much like the <cfswitch> and <cfcase>tags. Switch statements essentially implement a series of if-then-else statementswith an optional default case.The syntax of the switch statement is as follows:

switch(expression)

{

case constant:

...

[case constant:]

...

[default:]

...

}

Just like with the <cfswitch> and <cfcase> tags, the CFML interpreter evaluates theswitch expression and jumps to the case statement whose constant is equal to thevalue of the switch expression or to the default case if a matching case cannot befound.The CFML interpreter begins execution at this case statement and does not stop

35 0672324628 AppD 6/8/05 11:11 AM Page 345

Page 369: ColdFusion MX Developer's Cookbook (Developer's Library)

346 Appendix D Converting Between Tags and Scripting

until it reaches a break statement or the end of the switch statement. Make sure thatyou put break statements at the end of each case unless you intend for subsequentcases to execute as well.

For example, the following switch statement sets the value of the variable colordepending on the value of the choice variable:

<cfscript>

choice = form.choice;

switch(choice)

{

case “0”:

color=”red”;

break;

case “1”:

color=”blue”;

break;

case “2”:

color=”yellow”;

break;

case “3”:

color=”green”;

break;

default:

color=”purple”;

break

}

</cfscript>

Exception HandlingColdFusion scripts should also check for and catch any exceptions that might occur(exception handling concepts are covered in Chapter 8,“Exception Handling”). Scriptsuse the try and catch statements to handle exceptions.The syntax is as follows:

try

{

// Exception-prone logic

}

catch(ExceptionType ExceptionVariable)

{

// Exception-handling logic

}

[catch(ExceptionType ExceptionVariable) {}]

You can supply unique catch blocks for different types of expressions by specifying theexception type in the catch block. For example, the following code catches all

35 0672324628 AppD 6/8/05 11:11 AM Page 346

Page 370: ColdFusion MX Developer's Cookbook (Developer's Library)

347

exceptions and provides specialized catch blocks for expression and applicationexceptions:try

{

// Risky logic omitted

}

catch (Expression exprException)

{

WriteOutput(“An expression exception occurred”);

}

catch (Application appException)

{

WriteOutput(“An application exception occurred”);

}

catch (Any exception)

{

WriteOutput(“A generic exception occurred”);

}

You should use this technique to provide fine-grained exception handlers that canrespond differently to different types of exceptions.Your exception handling code willusually do more than simply display an error message. For example, an attempt to open alog file might raise an exception if the file does not exist. Rather than print an error, youmight want to handle this exception by creating and opening an empty log file.

35 0672324628 AppD 6/8/05 11:11 AM Page 347

Page 371: ColdFusion MX Developer's Cookbook (Developer's Library)

35 0672324628 AppD 6/8/05 11:11 AM Page 348

Page 372: ColdFusion MX Developer's Cookbook (Developer's Library)

SYMBOLS* (asterisk), 19@ (at symbol), 208\ (backslash), 21-22[] (brackets), 20-21, 198^ (caret), 20, 199-200& (concatenation) operator, 7-8- (dash), 198-199$ (dollar sign), 20, 122% (percent symbol), 196-197. (period), 20| (pipe character), 21+ (plus sign), 19? (question mark), 19_ (underscore), 197-198?wdsl suffix, 311

Aaccept attribute (<cffile> tag), 130,335

access attribute (<cffunction> tag),219

accessingcomponents, 267-268custom tags, 230EJBs (Enterprise JavaBeans), 322-326

acmeIntranet.cfm file, 172-174action attribute<cfcollection> tag, 152

<cfdirectory> tag, 135<cffile> tag, 126-130, 133<cfftp> tag, 148

<cfindex> tag, 153<cfldap> tag

add value, 143-144delete value, 147modify value, 144-145modifyDN value, 146

<cfobject> tag, 272<cfpop> tag, 141<cfwddx> tag, 282

actionsCFML2JS, 283-284CFML2WDDX, 281-283WDDX2CFML, 285-286WDDX2JS, 286-287

addColumn() method, 294addEmployee stored procedure,211-212

addNewLine attribute (<cffile> tag),127-128

addQuery() method, 241, 245-249,253

addRow() method, 246-247, 255addRows() method, 294administration of charts, 123Administrator, 123aggregate data, grouping, 193aggregate functions, 46-47

conditions, 194tables, 192-193

aliases, 187-188:alnum: character class, 22:alpha: character class, 22ampersand (&), 7-8

Index

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 349

Page 373: ColdFusion MX Developer's Cookbook (Developer's Library)

350 analyzing code

analyzing code, 339AND operator, 186-187any data type, 219Any exception, 105Apache AXIS WSDL2Java tool,315-316

Apache Jakarta Project Web site, 331Apache XML Project Web site, 331app column (CDATA table), 99appending to files, 127-128Application exceptions, 104Application.cfm file, 91, 165applications

application scope, 92-94authentication example

acmeIntranet.cfm, 172-174application.cfm, 165Authenticator.cfm, 167-168DatabaseAuthenticator.cfm, 168-169LDAPAuthenticator.cfm, 169-172loginForm.cfm, 166-167loginLogic.cfm, 165-166role table, 176SimpleAuthenticator.cfm, 168user table, 175user.cfm, 167user_roles table, 176

Client Management, 96-97client state information

storing in database, 99-100storing in Registry, 97-98storing with cookies, 98-99

creating, 91-93Session Management, 95-96

applicationTimeout attribute(<cfapplication> tag), 92-93

argumentcollection attribute(<cfobject> tag), 264

argumentscfencode.exe, 236functions, 220-221StructSort() function, 64

array data type, 219, 284-285ArrayAppend() function, 38-39, 47ArrayAvg() function, 46ArrayBoundException, 40ArrayClear() function, 47ArrayDelete() function, 47ArrayIsEmpty() function, 49ArrayLen() function, 40, 49ArrayMax() function, 46ArrayMin() function, 46ArrayNew() function, 37-38, 44-47ArrayPrepend() function, 38-39, 47ArrayResize() function, 38, 48arrays

converting lists to, 25-26, 48converting to lists, 48creating, 37-38defined, 37displaying values in, 39-40dynamically sized arrays, 38elements

adding, 38-39counting, 40defined, 37index, 37manipulating, 41sorting, 41-44

functionsaggregate functions, 46-47ArrayAppend(), 38-39, 47ArrayAvg(), 46ArrayClear(), 47ArrayDelete(), 47ArrayIsEmpty(), 49ArrayLen(), 40, 49ArrayMax(), 46

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 350

Page 374: ColdFusion MX Developer's Cookbook (Developer's Library)

351attributes

ArrayMin(), 46ArrayNew(), 37-38, 44-47ArrayPrepend(), 38-39, 47ArrayResize(), 38, 48ArraySet(), 48ArraySort(), 41-43, 48ArraySum(), 46ArraySwap(), 48ArrayToList(), 48information functions, 48-49IsArray(), 49ListToArray(), 48utility functions, 47-48

looping through, 40manipulating values in, 41multidimensional arrays, 44-45printing contents of, 344returning information about, 48-49sizing, 38swapping values in, 48when to use, 37

ArraySet() function, 48ArraySort() function, 41-43, 48ArraySum() function, 46ArraySwap() function, 48ArrayToList() function, 48AS statement, 187-188, 205Asc() function, 9ASCII character codes, 9assignment statements, 342AssocAttribs key (ThisTag variable),233

associative arrays. See structuresasterisk (*), 19at symbol (@), 208attacks (security)

cross-site scripting, 336-337DOS (denial of service) attacks,

335-336file uploading, 335

sandbox security, 337security Web sites, 337-338session hijacking, 333-334URL injection hacking, 334-335

attemptedServerFile key (cffile structure), 131

attributeExists() method, 241-243,249-251

attributesC++ CFX tags, 250-251<cfapplication> tag

applicationTimeout, 92-93clientManagement, 92-93clientStorage, 92, 97-99name, 92sessionManagement, 92-93sessionTimeout, 92setClientCookies, 92setDomainCookies, 92

<cfargument> tag, 220<cfchart> tag, 115-116, 122-123<cfchartseries> tag, 118<cfcollection> tag, 152<cfcomponent> tag

displayname, 261extends, 265-267hint, 261

<cfdirectory> tag, 135<cffile> tag

accept, 130, 335action, 126-130, 133addNewLine, 127-128attributes, 127-130, 133charset, 126-128, 133destination, 130, 133file, 126-128filefield, 130mode, 127-130, 133nameConflict, 130output, 127-128

How can we make this index more useful? Email us at [email protected]

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 351

Page 375: ColdFusion MX Developer's Cookbook (Developer's Library)

352 attributes

ServerFileExt, 335source, 133variable, 126

<cfftp> tag, 148<cffunction> tag, 219, 222-223<cfhttp> tag, 138-139<cfindex> tag, 153<cfloop> tag, 31-33<cfmail> tag, 140<cfobject> tag

action, 272argumentcollection, 264class, 272component, 262-264, 273context, 273locale, 273name, 272server, 273type, 272webservice, 273

<cfpop> tag, 141<cfprocparam> tag, 210-211<cfprocresult> tag, 207<cfquery> tag

blockFactor, 68cachedAfter, 68, 76-77cachedWithin, 68, 76-77Datasource, 68, 73-74dbType, 68, 73-74Debug, 68maxRows, 68Name, 68Password, 68Timeout, 68Username, 68

<cfsearch> tag, 156<cfstoredproc> tag, 207<cfthrow> tag, 107<custom> tags, 230-231

Java CFX tags, 241-243LDAP directory entries, 145-146stored procedures

defining in Microsoft SQL Server,207-208

defining in Oracle, 208-209output parameters, 211-212passing, 209-211

XML documents, 297XML elements, 298-300

attributes attribute (<cffile> tag),127-130, 133

Attributes structure, 230-231authentication and authorization,159

authentication exampleacmeIntranet.cfm, 172-174application.cfm, 165Authenticator.cfm, 167-168DatabaseAuthenticator.cfm, 168-169LDAPAuthenticator.cfm, 169-172loginForm.cfm, 166-167loginLogic.cfm, 165-166role table, 176SimpleAuthenticator.cfm, 168user table, 175user.cfm, 167user_roles table, 176

authentication realm, 159blocks of code, 162-163functions, 164j_password field, 161-162j_username field, 161-162logins, 160logouts, 160-161user IDs, 162user roles, 163

Authenticator.cfm file, 167-168AVG() function, 192-193

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 352

Page 376: ColdFusion MX Developer's Cookbook (Developer's Library)

353CFCs (components)

BbackgroundColor attribute(<cfchart> tag), 115

backslash (\), 21-22bcc attribute (<cfmail> tag), 140beans, accessing, 322-326binary data type, 219, 286biu.cfm custom tag, 232biuClient.cfm template, 232:blank: character class, 22blockfactor attribute (<cfstoredproc> tag), 207

blockFactor parameter (<cfquery> tag), 68

blocks of code, authorizing, 162-163body attribute (<cfindex> tag), 153boolean data type, 218, 284-286brackets ([]), 20-21, 198break statements, 345breaking loops, 345

CC++ CFX tags, 239

attributes, 250-251<CFX_GetMemoryStatus>, 251-253<CFX_ReverseQuery>, 253-255<CFX_SubString>, 250-251<CFX_WriteMemoryStatus>,

247-248ColdFusion variables, 251-253creating, 247-249installing, 257-258queries, 253-255registering, 257-258

cachedAfter parameter (<cfquery> tag), 68, 76-77

cachedWithin parameter (<cfquery> tag), 68, 76-77

caching queries, 76-77

CallEJB.cfm listing, 324calling

methods, 263-264, 273-274.NET, 312-314stored procedures, 206-207Web services

<cfinvoke> tag, 306-307Java, 315-316

cardinal numbering, 25caret (^), 20, 199-200catch statements, 346-347catching exceptions

multiple exceptions, 104-105single exceptions, 103

cc attribute (<cfmail> tag), 140CCFXQuery class, 255CCFXRequest class, 249-250CDATA table, 99CERT Coordination Center, 338CF Bookmark Web site, 329CF Bug Hunt Web site, 329CF FAQ Web site, 329<cfapplication> tag, 91-93, 97-99<cfargument> tag, 220-221<cfcatch> tag, 102-105cfcatch variable, 106<cfchart> tag, 113-116, 122-123<cfchartdata> tag, 113-114, 121<cfchartseries> tag, 113-114,117-118

<cfcollection> tag, 151-152<cfcomponent> tag, 259-261

displayname attribute, 261extends attribute, 265-267hint attribute, 261

CFCs (components)accessing, 267-268counter.cfc, 263creating, 259-261

How can we make this index more useful? Email us at [email protected]

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 353

Page 377: ColdFusion MX Developer's Cookbook (Developer's Library)

354 CFCs (components)

employee.cfc, 265encapsulation, 261inheritance, 265-267instantiating, 262-263invoking component methods,

263-264light.cfc, 259-262manager.cfc, 266meta data, 268-269

CFCustomTags.com Web site, 329CFCZone Web site, 329CFDEV Web site, 329CFDEVX Web site, 329<cfdirectory> tag, 134-136<cfdump> tag, 307cfencode.exe command, 235-236cffile structure, 131-132<cffile> tag, 15

accept attribute, 335append action, 127-128attributes

accept, 130action, 126-130, 133addNewLine, 127-128attributes, 127-130, 133charset, 126-128, 133destination, 130, 133file, 126-128filefield, 130mode, 127-130, 133nameConflict, 130output, 127-128source, 133variable, 126

copy action, 134delete action, 134move action, 133read action, 125-126rename action, 133-134ServerFileExt attribute, 335

upload action, 129-132write action, 126-127writing files, 126

<cfftp> tag, 147-149<cffunction> tag, 164, 218-219,222-223, 259-261, 309

<cfheader> tag, 288<cfhttp> tag, 138-139cfhttp variable, 139CFHub.com Web site, 330cfid column

CDATA table, 99CGLOBAL table, 100

CFID variable, 333-334<cfimport> tag, 237-238<cfinclude> tag, 174<cfindex> tag, 152-153<cfinvoke> tag, 263-264, 306-307<cfinvokeargument> tag, 264<cfldap> tag, 141-147<cflogin> tag, 160, 177<cfloginuser> tag, 160<cflogout> tag, 160-161<cfloop> tag, 14-15, 31-35, 70-71<cfmail> tag, 140CFMCentral Web site, 330CFML (ColdFusion MarkupLanguage) scripts

<cfscript> tag, 341-343conversions

CFML to JavaScript, 283-284CFML to WDDX, 281-283WDDX to CFML, 285-286WDDX to JavaScript, 286-287

exception handling, 346-347if-then-else statements, 343loops, 343-345switch statements, 345-346

CFML2JS action, 283-284

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 354

Page 378: ColdFusion MX Developer's Cookbook (Developer's Library)

355CFX tags

CFML2WDDX action, 281-283<cfmodule> tag, 236-237<cfobject> tag, 262-263, 271,276-277, 307-308

action attribute, 272argumentcollection attribute, 264class attribute, 272component attribute, 262-264, 273context attribute, 273locale attribute, 273name attribute, 272server attribute, 273type attribute, 272webservice attribute, 273

<cfoutput> tag, 39-40, 70-71,190-191

<cfpop> tag, 140-141<cfprocparam> tag, 209-211<cfprocresult> tag, 206-207, 213<cfproperty> tag, 309-310<cfquery> tag, 67-69

blockFactor parameter, 68cachedAfter parameter, 68, 76-77cachedWithin parameter, 68, 76-77Datasource parameter, 68, 73-74dbType parameter, 68, 73-74Debug parameter, 68example, 67maxRows parameter, 68Name parameter, 68parameters, 68Password parameter, 68Timeout parameter, 68Username parameter, 68

<cfqueryparam> tag, 200-201, 334<cfrethrow> tag, 108-109<cfreturn> tag, 222CFScript statements, 341<cfscript> tag, 341-343

<cfsearch> tag, 155-157<cfset> tag, 94<cfsetting> tag, 288cfsqltype attribute (<cfprocparam>tag), 210

<cfstoredproc> tag, 206-207<cfthrow> tag, 107-108CFTOKEN variable, 333-334<cftry> tag, 102-104<cfwddx> tag

CFML2JS action, 283-284CFML2WDDX action, 281-283WDDX2CFML action, 285-286WDDX2JS action, 286-287

CFX tags, 239C++ CFX tags

attributes, 250-251<CFX_GetMemoryStatus>,

251-253<CFX_ReverseQuery>, 253-255<CFX_SubString>, 250-251<CFX_WriteMemoryStatus>,

247-248ColdFusion variables, 251-253creating, 247-249installing, 257-258queries, 253-255registering, 257-258

Java CFX tagsattributes, 241-243<CFX_GetMemoryStatus>,

244-245<CFX_ReverseQuery>, 245-246<CFX_SubString>, 242<CFX_WriteMemoryStatus>,

240-241ColdFusion variables, 244-245creating, 240-241CustomTag interface, 240queries, 245-247registering, 256

How can we make this index more useful? Email us at [email protected]

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 355

Page 379: ColdFusion MX Developer's Cookbook (Developer's Library)

356 <cfxml> tag

<cfxml> tag, 295-296<CFX_GetMemoryStatus> tag

C++ code listing, 251-253Java code listing, 244-245

<CFX_ReverseQuery> tagC++ code listing, 253-255Java code listing, 245-246

<CFX_SubString> tagC++ code listing, 250-251Java code listing, 242

<CFX_WriteMemoryStatus> tagC++ code listing, 247-248Java code listing, 240-241

CGLOBAL table, 100changing

list delimiters, 24-25list values, 28-29

character classes, 22characters. See also strings

ASCII character codes, 9brackets ([]), 20-21character classes, 22escape characters, 21-22matching

excluded characters, 199-200groups of characters, 198range of characters, 198-199single characters, 197-198

pipe character (|), 21quantifiers, 19wildcards, 20

charset attribute<cffile> tag, 126-128, 133<cfhttp> tag, 139

chartHeight attribute (<cfchart>tag), 115

charts, 113administering with ColdFusion

Administrator, 123chart containers, 114-116

chart seriesmanaging, 117-118populating with explicit values, 121

click-through behaviors, 123creating, 113-114populating with query values, 121-122supported CFMX chart types,

118-120chartWidth attribute (<cfchart>tag), 115

child elements (XML), 300choosing list delimiters, 24Chr() function, 9class attribute (<cfobject> tag), 272classes

CCFXQuery, 255CCFXRequest, 249-250character classes, 22DogServiceLocator, 316RecordSet, 294WddxDeserializer, 292-294WddxSerializer, 290-291

clauses,WHERE, 186-187click-through behaviors, 123Client Management, 96-97client prefix, 96-97clientDirectory key (cffile structure),131

clientFile key (cffile structure), 131clientFileExt key (cffile structure),131-132

clientFileName key (cffile structure),131-132

clientManagement attribute (<cfapplication> tag), 92-93

clientsClient Management, 96-97client state information

storing in database, 99-100storing in Registry, 97-98storing with cookies, 98-99

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 356

Page 380: ColdFusion MX Developer's Cookbook (Developer's Library)

357cookies

clientStorage attribute (<cfapplication>> tag), 92, 97-99

:cntrl: character class, 22code blocks, authorizing, 162-163ColdFusion 5, migrating toColdFusion MX, 339-340

ColdFusion Administrator, 123ColdFusion Developers Journal, 330ColdFusion FAQ Web site, 330collection attribute

<cfcollection> tag, 152<cfindex> tag, 153<cfsearch> tag, 156

collections (Verity)adding data to, 152-155creating, 151-152searching, 155-157

colorList attribute (<cfchartseries>tag), 118

columnList variable, 72Columns attribute (<cfhttp> tag),138

COM (Component Object Model)objects, 276-277

com2java.exe program, 277combining strings, 7-8comma-delimited lists, 8Common Object Request BrokerArchitecture (CORBA) objects,277-280

comparing dates, 82-83compatibility, analyzing code for,339

Compatibility Analyzer, 339component attribute (<cfobject>tag), 262-264, 273

Component Object Model (COM)objects, 276-277

componentName data type, 219

components (CFCs). See also objectsaccessing, 267-268counter.cfc, 263creating, 259-261employee.cfc, 265encapsulation, 261inheritance, 265-267instantiating, 262-263invoking component methods,

263-264light.cfc, 259-262manager.cfc, 266meta data, 268-269

concatenating strings, 7-8concatenation (&) operator, 7-8condition attribute (<cfloop> tag),33

conditional loops, 33connection attribute (<cfftp> tag),148

containers, 114-116contentSubType key (cffile structure), 131

contentType key (cffile structure),131

context attribute (<cfobject> tag),273

continue statements, 345conversions

arrays to lists, 48CFML to JavaScript, 283-284CFML to WDDX, 281-283Java to WDDX, 290-292lists to arrays, 25-26, 48queries to lists, 75-76WDDX to CFML, 285-286WDDX to Java, 292-294WDDX to JavaScript, 286-287

cookies, 98-99

How can we make this index more useful? Email us at [email protected]

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 357

Page 381: ColdFusion MX Developer's Cookbook (Developer's Library)

358 copying

copyingfiles, 132-134structures, 61-63

CORBA (Common Object RequestBroker Architecture) objects,277-280

COUNT() function, 193counter.cfc component, 263counting array elements, 40CREATE OR REPLACE statement,205

CREATE PROCEDURE statement,204-205

CreateDate() function, 80CreateDateTime() function, 80CreateObject() function, 262-263,271-273, 277

createStringSet() method, 249CreateTime() function, 80CreateTimeSpan() function, 85-86,93

criteria attribute (<cfsearch> tag),156

cross-site scripting, 336-337CSS (cross-site scripting), 336-337currentRow variable, 72custom tags

accessing, 230attributes, 230-231biu.cfm, 232calling regardless of location, 236-237C++ CFX tags

attributes, 250-251<CFX_GetMemoryStatus>,

251-253<CFX_ReverseQuery>, 253-255<CFX_SubString>, 250-251<CFX_WriteMemoryStatus>,

247-248ColdFusion variables, 251-253creating, 247-249

installing, 257-258queries, 253-255registering, 257-258

<cfimport> tag, 237-238<cfmodule> tag, 236-237creating, 229-230encoding, 235-236getDomainTag.cfm, 231greetingTag.cfm, 230helloWorldTag.cfm, 229-230importing, 237-238Java CFX tags

attributes, 241-243<CFX_GetMemoryStatus>,

244-245<CFX_ReverseQuery>, 245-246<CFX_SubString>, 242<CFX_WriteMemoryStatus>,

240-241ColdFusion variables, 244-245creating, 240-241CustomTag interface, 240installing, 256queries, 245-247registering, 256

mailto.cfm, 234nested tags, 234-235return results, 231-232start/end tags, 232-233

custom1 attribute (query objects),156

custom2 attribute (query objects),156

CustomTag interface, 240Custom_Type exceptions, 105

Ddash (-), 198-199data column

CDATA table, 99CGLOBAL table, 100

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 358

Page 382: ColdFusion MX Developer's Cookbook (Developer's Library)

359databases

data types. See also arraysany, 219array, 219, 284-285binary, 219, 286boolean, 218, 284-286componentName, 219date, 219, 284-285

comparing, 82-83date formatting, 80-82date information functions, 86-87Date objects, 79-80DateTime objects, 79-80determining time differences, 83-84functions, 80-88locale-specific dates/times, 88time formatting, 84-85Time objectscreating, 79-80time spans, 85-86

guid, 219IDL-to-ColdFusion type mappings,

279-280Number, 284-286numeric, 219query, 219, 284-285string, 218, 284-286structures, 51, 219, 284-286

copying, 61-63creating, 52displaying values in, 57dot notation, 58-59information functions, 52-53inserting values into, 55-56key names, 57looping over, 59-60management functions, 53-55naming, 52sorting, 63-66updating values in, 56-57utility functions, 60-61

uuid, 219variableName, 219void, 219Web services, 309-311

dataBackgroundColor attribute(<cfchart> tag), 115

Database exceptions, 104DatabaseAuthenticator.cfm file,168-169

databasesaggregate functions, 192-194migrating to ColdFusion MX, 340queries. See also SQL statements

C++ CFX tags, 253-255caching, 76-77converting to lists, 75-76creating manually, 69-70creating with <cfquery> tag, 67-69displaying query results, 70-71functions, 69-70, 75-76in-memory queries, 73-74Java CFX tags, 245-247populating charts with, 121-122prepared statements, 200-202query variables, 71-73

storing client state information in,99-100

tablesadding rows to, 183aggregate functions, 192-194aliases, 187-188authentication application, 175-176CDATA, 99CGLOBAL, 100deleting rows from, 184department, 182employees, 181-182employee_projects, 182grouping data in, 190-193joining, 189-191

How can we make this index more useful? Email us at [email protected]

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 359

Page 383: ColdFusion MX Developer's Cookbook (Developer's Library)

360 databases

pattern matching, 196-200projects, 182selecting data in, 185-189, 192-196updating, 183-184

datasource attribute<cfquery> tag, 68, 73-74<cfstoredproc> tag, 207

date data type, 219, 284-285Date objects, 79-80DateCompare() function, 82-83DateDiff() function, 83-84DateFormat() function, 80-82dates/times

comparing, 82-83date formatting, 80-82date information functions, 86-87Date objects, 79-80DateTime objects, 79-80determining time differences, 83-84functions

CreateDate(), 80CreateDateTime(), 80CreateTime(), 80CreateTimeSpan(), 85-86DateCompare(), 82-83DateDiff(), 83-84DateFormat(), 80-82Day(), 87DayOfWeek(), 87DayOfWeekAsString(), 87DayOfYear(), 87DaysInMonth(), 87DaysInYear(), 87FirstDayOfMonth(), 87Hour(), 87IsLeapYear(), 87LSDateFormat(), 88LSTimeFormat(), 88Minute(), 87

Month(), 87MonthAsString(), 87Quarter(), 87Second(), 87TimeFormat(), 84-85Week(), 87Year(), 87

locale-specific dates/times, 88time formatting, 84-85Time objects, 79-80time spans, 85-86

DateTime objects, 79-80Day() function, 87DayOfWeek() function, 87DayOfWeekAsString() function, 87DayOfYear() function, 87DaysInMonth() function, 87DaysInYear() function, 87dbType parameter (<cfquery> tag),68, 73-74

DCOM (Distributed ComponentObject Model) objects, 276-277

debug attribute<cfstoredproc> tag, 207<cfquery> tag, 68

debug() method, 243, 249declaring functions, 218-219Decrypt() function, 12-13decrypting strings, 12-13default attribute (<cfargument> tag), 220

Defusion Web site, 330DELETE statement, 184deleting

files, 132-134LDAP directories, 147table rows, 184

Delimiter attribute (<cfhttp> tag),138

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 360

Page 384: ColdFusion MX Developer's Cookbook (Developer's Library)

361elements

delimiterslist delimiters, 24-25string delimiting, 8

denial of service (DOS) attacks,335-336

department table, 182deploying Web services, 311deserializing WDDX (WebDistributed Data Exchange),292-294

destination attribute (<cffile> tag),130, 133

detail attribute (<cfthrow> tag), 107DEVMX Web site, 330:digit: character class, 22directories

adding entries, 143-144creating, 136deleting entries, 147entry attributes, 145-146listing contents of, 134-136naming, 136querying, 141-143removing, 136renaming entries, 146updating entries, 144-145

directory attribute (<cfdirectory> tag), 135

displayingarray values, 39-40query results, 70-71values in structures, 57

displayname attribute (<cfcomponent> tag), 261

DISTINCT statement, 192Distributed Component ObjectModel (DCOM) objects, 276-277

DLLs (Dynamic Link Libraries), 276do-while loops, 344

documentation, 340documents, XML, 295

child elements, 300creating from other objects, 298creating with <cfxml> tag, 295-296creating with XmlElemNew()

function, 296-298creating with XmlNew() function,

296-298element attributes, 298-300inner text, 300-301parsing, 299properties, 297searching, 301-302XSL transformations, 302-304

DogService interface, 316DogService Web service, 312-314DogServiceLocator class, 316dollar sign ($), 20, 122DOS (denial of service) attacks,335-336

dot notation, 58-59downloading files, 148-149Duplicate() function, 61-63, 298Dynamic Link Libraries (DLLs), 276dynamically sized arrays, 38

EEasyCFM.com Web site, 330EJBs (Enterprise JavaBeans), 322-326elements. See also tags

array elementsadding, 38-39counting, 40defined, 37index, 37looping through, 40manipulating, 41

How can we make this index more useful? Email us at [email protected]

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 361

Page 385: ColdFusion MX Developer's Cookbook (Developer's Library)

362 elements

returning information about, 48-49sorting, 41-44

list elementschanging values in, 28-29empty values, 26-28extracting, 25-26looping through, 31-33qualifiers, 30-31searching, 29-30sorting, 30

XML elementsattributes, 298-300child elements, 300inner text, 300-301

else statement, 343email, 140-141employee.cfc component, 265employee_projects table, 182employees table, 181-182empty list values, 26-28encapsulation, 261encoding custom tags, 235-236Encrypt() function, 12-13encrypting strings, 12-13end tags, 232-233Enterprise JavaBeans (EJBs), 322-326entries (LDAP directories)

adding, 143-144attributes, 145-146deleting, 147renaming, 146updating, 144-145

errorCode attribute (<cfthrow> tag), 107

errors. See exceptionsescape characters, 21-22Evolt Web site, 332

exceptions, 101-103Any exceptions, 105Application exceptions, 104ArrayBoundException, 40catching

multiple exceptions, 104-105single exceptions, 103

Custom_Type exceptions, 105Database exceptions, 104exception handlers, 346-347Expression exceptions, 104finding information about, 105-107Lock exceptions, 104MissingInclude, 104NonEmptyDirectoryCannotBeDelete

dException, 136NoSuchTemplateException, 267Object exceptions, 104re-throwing, 108-109SearchEngine exceptions, 105Security exceptions, 104Template exceptions, 104throwing, 107-108

excludinggroups of characters, 199ranges of characters, 199-200

ExecutionMode key (ThisTag variable), 233

executionTime variable, 72explicit Verity searches, 157Expression exceptions, 104extendedInfo attribute (<cfthrow> tag), 107

extends attribute (<cfcomponent>tag), 265-267

extends key, 268Extensible Markup Language.

See XMLextensions attribute (<cfindex> tag),153

extracting list elements, 25-26

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 362

Page 386: ColdFusion MX Developer's Cookbook (Developer's Library)

363FROM statement

Ffactorial.cfm listing, 319FAQs

CF FAQ Web site, 329ColdFusion FAQ Web site, 330

fields, 161-162file attribute

<cffile> tag, 126-128<cfhttp> tag, 138

fileExisted key (cffile structure), 131FileExists() function, 128filefield attribute (<cffile> tag), 130files, 125

appending to, 127-128Application.cfm, 91authentication application

acmeIntranet.cfm, 172-174application.cfm, 165Authenticator.cfm, 167-168DatabaseAuthenticator.cfm, 168-169LDAPAuthenticator.cfm, 169-172loginForm.cfm, 166-167loginLogic.cfm, 165-166SimpleAuthenticator.cfm, 168user.cfm, 167

copying, 132-134deleting, 132-134downloading with FTP, 148-149moving, 132-134reading, 15, 125-126renaming, 132-134uploading, 129-132, 335uploading with FTP, 147-148verifying existence of, 128WDSL files, 311writing, 126-127

fileSize key (cffile structure), 131fileWasAppended key (cffile structure), 131

fileWasOverwritten key (cffile structure), 131

fileWasRenamed key (cffile structure), 131

fileWasSaved key (cffile structure),131

filter attribute (<cfdirectory> tag),135

Find() function, 11, 16-17findColumn() method, 294finding substrings, 18-19FindNoCase() function, 11, 16-17FindOneOf() function, 11FirstDayOfMonth() function, 87FirstRowAsHeaders attribute(<cfhttp> tag), 138

Flight object, 309font attribute (<cfchart> tag), 115fontBold attribute (<cfchart> tag),115

fontItalic attribute (<cfchart> tag),115

fontSize attribute (<cfchart> tag),115

for loops, 344for-in loops, 344foregroundColor attribute(<cfchart> tag), 115

format attribute (<cfchart> tag),115

formattingdates, 79-82times, 84-85

forms, parsing, 34-35forward() function, 318forwarding requests to servlets/JSPs,318

from attribute (<cfmail> tag), 140FROM statement, 188-189

How can we make this index more useful? Email us at [email protected]

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 363

Page 387: ColdFusion MX Developer's Cookbook (Developer's Library)

364 FTP (File Transfer Protocol) servers

FTP (File Transfer Protocol) serversdownloading files, 148-149uploading files, 147-148

Full As a Goog Web site, 330FULL OUTER JOIN statement, 191function-call statements, 343functions and methods

addColumn(), 294addQuery(), 241, 245-249, 253addRow(), 246-247, 255, 294attributeExists(), 241-243, 249-251ArrayAppend(), 38-39, 47ArrayAvg(), 46ArrayClear(), 47ArrayDelete(), 47ArrayIsEmpty(), 49ArrayLen(), 40, 49ArrayMax(), 46ArrayMin(), 46ArrayNew(), 37-38, 44-47ArrayPrepend(), 38-39, 47ArrayResize(), 38, 48ArraySet(), 48ArraySort(), 41-43, 48ArraySum(), 46ArraySwap(), 48ArrayToList(), 48Asc(), 9authorizing, 164AVG(), 192-193calling, 263-264Chr(), 9COUNT(), 193CreateDate(), 80CreateDateTime(), 80CreateObject(), 262-263, 271-273,

277createStringSet(), 249CreateTime(), 80CreateTimeSpan(), 85-86, 93

DateCompare(), 82-83DateDiff(), 83-84DateFormat(), 80-82Day(), 87DayOfWeek(), 87DayOfWeekAsString(), 87DayOfYear(), 87DaysInMonth(), 87DaysInYear(), 87debug(), 243, 249Decrypt(), 12-13Duplicate(), 61-63, 298Encrypt(), 12-13FileExists(), 128Find(), 11, 16-17findColumn(), 294FindNoCase(), 11, 16-17FindOneOf(), 11FirstDayOfMonth(), 87forward(), 318getAttribute(), 241-243, 249-251getAttributeList(), 243, 249GetAuthUser(), 162getColumnCount(), 294getColumnIndex(), 246, 255getColumnNames(), 294getColumns(), 246-247, 255getData(), 246-247, 255getDogServiceCfc(), 316getIntAttribute(), 241-243getField(), 294GetMetaData(), 268-269getName(), 246, 255getQuery(), 243-249, 253-255GetPageContext(), 318getRowCount(), 246-247, 255, 294Hash(), 13-14Hour(), 87HTMLEditFormat, 283, 337include(), 319

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 364

Page 388: ColdFusion MX Developer's Cookbook (Developer's Library)

365functions and methods

invoking, 273-274IsArray(), 49IsIE(), 222IsLeapYear(), 87IsStruct(), 52-53IsUserInRole(), 162-163, 176Left(), 10-11Len(), 11ListAppend(), 24ListChangeDelims(), 24-25ListDeleteAt(), 28-29ListFind(), 29-30ListFindNoCase(), 29ListFirst(), 26ListGetAt(), 25ListInsertAt(), 28-29ListPrepend(), 24ListQualify(), 30-31ListRest(), 26ListSetAt(), 28-29ListSort(), 30ListToArray(), 25-26, 48LSDateFormat(), 88LSTimeFormat(), 88LTrim(), 11MAX(), 193Mid(), 11, 14migrating to ColdFusion MX, 340MIN(), 193Minute(), 87Month(), 87MonthAsString(), 87noOutputAttribute(), 223outputTrue(), 223overriding, 267Power(), 223-225processRequest(), 241ProcessTagRequest(), 247-249Quarter(), 87QueryAddColumn(), 70

QueryAddRow(), 69-70QueryNew(), 69-70QuerySetCall(), 69-70QuotedValueList(), 75-76REFind(), 18-19remote, 315RemoveChars(), 11Replace(), 11, 17-18ReplaceNoCase(), 11, 17-18reThrowException(), 249Right(), 10-11RTrim(), 11Second(), 87setData(), 246-247, 255setField(), 294setVariable(), 244-245, 249-253Split(), 221StripCR(), 12StructAppend(), 53-54StructClear(), 54StructCopy(), 54, 61-63StructCount(), 53StructFind(), 54, 57StructFindKey(), 61StructFindValue(), 61StructGet(), 61StructInsert(), 54-56StructIsEmpty(), 52-53StructKeyArray(), 61StructKeyExists(), 52-53StructKeyList(), 61StructKeyLists(), 52, 59-60StructNew(), 52-54StructSort(), 54, 63-66StructUpdate(), 54-56SUM(), 193SuperSplit(), 221throwException(), 249TimeFormat(), 84-85ToBase64(), 126

How can we make this index more useful? Email us at [email protected]

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 365

Page 389: ColdFusion MX Developer's Cookbook (Developer's Library)

366 functions and methods

Trim(), 12, 26user-defined functions, 217

arguments, 220-221data types, 218-219declaring, 218-219recursive functions, 223-225references, 225-227return values, 222suppressing output, 222-223

ValueList(), 75Week(), 87write(), 240-241, 249writeDebug(), 241, 249WriteOutput(), 341XmlElemNew(), 296-298XmlNew(), 296-298XmlParse(), 299XmlSearch(), 301-302XmlTransform(), 302-303Year(), 87

functions key, 268Fusion Authority Web site, 330

G/g argument (<cfencode.exe), 236GeneratedContent key (ThisTagvariable), 233

generating WDSL files, 311getAttribute() method, 241-243,249-251

getAttributeList() method, 243, 249GetAuthUser() function, 162getColumnCount() method, 294getColumnIndex() method, 246, 255getColumnNames() method, 294getColumns() method, 246-247, 255getData() method, 246-247, 255getDepartmentsAndProjects storedprocedure, 213

getDogServiceCfc() function, 316getDomainClient.cfm template, 232getDomainTag.cfm custom tag, 231getField() method, 294getIntAttribute() method, 241-243GetMetaData() function, 268-269getName() method, 246, 255GetPageContext() function, 318getQuery() method, 243-249,253-255

getRowCount() method, 246-247,255, 294

giveRaise stored procedure, 204-205:graph: character class, 22greetingClient.cfm template, 231greetingTag.cfm custom tag, 230gridlines attribute (<cfchart> tag),115

GROUP BY statement, 193grouping data, 163

<cfoutput> tag, 190-191GROUP BY clause, 193

groups of characters, matching,198-199

guid data type, 219

H/h argument (cfencode.exe), 236handling exceptions. See exceptionsHasEndTag key (ThisTag variable),233

Hash() function, 13-14hashing strings, 13-14HAVING statement, 194helloWorldTag.cfm, 229-230hint attribute

<cfcomponent> tag, 261<cffunction> tag, 219

Hour() function, 87House of Fusion Web site, 330

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 366

Page 390: ColdFusion MX Developer's Cookbook (Developer's Library)

367iterating

HTMLEditFormat() function, 283,337

HTTP requests, 137-139hyphen (-), 198-199

IIDL (Interface DefinitionLanguage), 278-280

IDs, user IDs, 162if-then-else statements, 343importing custom tags, 237-238IN statement, 194-196, 209include() function, 319include.jsp listing, 319including servlets/JSPs, 318-319infile argument (cfencode.exe), 236information functions (arrays), 48-49inheritance, 265-267in-memory queries, 73-74inner text (XML), 300-301input attribute (<cfwddx> tag), 282input forms, parsing, 34-35INSERT INTO statement, 183inserting

array elements, 38-39table rows, 183values into structures, 55-56

installing CFX tags, 257-258instantiating

components, 262-263objects, 271-273Web services, 307-308

Interface Definition Language(IDL), 278-280

interfacesCustomTag, 240DogService, 316Query, 246

Request, 243Response, 241

Internet protocolsFTP

downloading files, 148-149uploading files, 147-148

HTTP requests, 137-139LDAP directories

adding entries, 143-144deleting entries, 147entry attributes, 145-146querying, 141-143renaming entries, 146updating entries, 144-145

POP servers, 140-141SMTP servers, 140

invokingmethods, 263-264, 273-274.NET, 312-314stored procedures, 206-207Web services

cfinvoke tag, 306-307Java, 315-316

IsArray() function, 49IsIE() function, 222IsLeapYear() function, 87IsStruct() function, 52-53IsUserInRole() function, 162-163,176

itemColumn attribute (<cfchartseries> tag), 118

iteratingthrough lists, 31-33through strings, 14-15

How can we make this index more useful? Email us at [email protected]

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 367

Page 391: ColdFusion MX Developer's Cookbook (Developer's Library)

368 J2EE interoperability

JJ2EE interoperability, 317

EJB access, 322-326JSPs

accessing ColdFusion pages from, 319data sharing, 320-322forwarding requests to, 318including, 318-319

servletsaccessing ColdFusion pages from, 319data sharing, 320-322forwarding requests to, 318including, 318-319

Jakarta Project Web site, 331Java

CFX tags, 239attributes, 241-243<CFX_GetMemoryStatus>,

244-245<CFX_ReverseQuery>, 245-246<CFX_SubString>, 242<CFX_WriteMemoryStatus>,

240-241ColdFusion variables, 244-245creating, 240-241CustomTag interface, 240installing, 256queries, 245-247registering, 256

invoking Web services with, 315-316Java-to-COM bridge, 277JavaBeans, 322-326JSPs (JavaServer Pages)

accessing ColdFusion pages from, 319data sharing, 320-322forwarding requests to, 318including, 318-319

objects, 275-276converting to WDDX, 290-292creating, 271-273, 292-294methods, 273-274

Web sites, 331Java-to-COM bridge, 277JavaBeans, 322-326JavaScript, converting CFML to,283-284

JavaServer Pages (JSPs)accessing ColdFusion pages from, 319data sharing, 320-322forwarding requests to, 318including, 318-319

Jintegra, 277joining tables, 189-191journals, ColdFusion DevelopersJournal, 330

JSP Resource Index Web site, 331JSP Tags Web site, 331JSPs (JavaServer Pages)

accessing ColdFusion pages from, 319data sharing, 320-322forwarding requests to, 318including, 318-319

j_password field, 161-162j_username field, 161-162

Kkey attribute

<cfindex> tag, 153query objects, 157

key lists, looping through, 32-33keys, 57, 268-269keywords

AND, 186-187AS, 187-188, 205CREATE OR REPLACE, 205CREATE PROCEDURE, 204-205

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 368

Page 392: ColdFusion MX Developer's Cookbook (Developer's Library)

369ListSetAt() function

DELETE, 184DISTINCT, 192FROM, 188-189FULL OUTER JOIN, 191GROUP BY, 193HAVING, 194IN, 194-196, 209INSERT INTO, 183LEFT OUTER JOIN, 191LIKE, 196-199OR, 186-187ORDER BY, 187OUTPUT, 211-212RIGHT OUTER JOIN, 191SELECT, 185SET, 183-184UPDATE, 183-184VALUES, 183WHERE, 185-186, 189-190

LlabelFormat attribute (<cfchart> tag), 115

language attribute<cfcollection> tag, 152<cfindex> tag, 153<cfsearch> tag, 156

LDAP (Lightweight DirectoryAccess Protocol) directories

adding entries, 143-144deleting entries, 147entry attributes, 145-146querying, 141-143renaming entries, 146updating entries, 144-145

LDAPAuthenticator.cfm file, 169-172LEFT OUTER JOIN statement, 191Left() function, 10-11Len() function, 11

libraries (tag), importing, 237-238light.cfc component, 259, 261-262Lightweight Directory AccessProtocol. See LDAP directories

LIKE operator[] (brackets) wildcard, 198^ (caret) wildcard, 199-200- (dash) wildcard, 198-199% (percent symbol) wildcard, 196-197_ (underscore) wildcard, 197-198

list attribute (<cfloop> tag), 31-33ListAppend() function, 24ListChangeDelims() function, 24-25ListDeleteAt() function, 28-29ListFind() function, 29-30ListFindNoCase() function, 29ListFirst() function, 26ListGetAt() function, 25listing directory contents, 134-136ListInsertAt() function, 28-29ListPrepend() function, 24ListQualify() function, 30-31ListRest() function, 26lists

changing values in, 28-29comma-delimited lists, 8converting arrays to, 48converting queries to, 75-76converting to arrays, 25-26, 48creating, 23-24delimiters, 24-25empty values, 26-28extracting elements from, 25-26looping through, 31-33parsing input forms, 34-35qualifiers, 30-31searching, 29-30sorting, 30

ListSetAt() function, 28-29

How can we make this index more useful? Email us at [email protected]

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 369

Page 393: ColdFusion MX Developer's Cookbook (Developer's Library)

370 ListSort() function

ListSort() function, 30ListToArray() function, 25-26, 48Live Documentation Web site, 330locale attribute (<cfobject> tag), 273locale dates/times, 88localfile attribute (<cfftp> tag),148-149

localization, 340Lock exceptions, 104logging in/out users, 160-161logical OR operations, 21loginForm.cfm file, 166-167loginLogic.cfm file, 165-166looping

through array elements, 40through lists, 31-33through strings, 14-15over structures, 59-60

loops, 343-345:lower: character class, 22LSDateFormat() function, 88LSTimeFormat() function, 88LTrim() function, 11lvisit column (CGLOBAL table), 100

MMacromedia ColdFusion SupportCenter, 331

Macromedia Designer andDeveloper Center Web site, 330

Macromedia Online Forums Website, 331

Macromedia Security Zone, 338magazines, ColdFusion DevelopersJournal, 330

mail. See emailmailto.cfm custom tag, 234

managementcharts

chart series, 117-118ColdFusion Administrator, 123

Client Management, 96-97Session Management, 95-96

manager.cfc component, 266manually creating queries, 69-70markerSize attribute

<cfchart> tag, 115<cfchartseries> tag, 118

mask valuesDateFormat() function, 81TimeFormat() function, 85

massmailer.cfm template, 234massmailerClient.cfm template, 234matching patterns

excluded characters, 199-200groups of characters, 198range of characters, 198-199single characters, 197-198wildcard patterns, 196-197

Math.java listing, 322MathBean.java listing, 323MathHome.java listing, 323MAX() function, 193maxlength attribute (<cfprocparam> tag), 211

maxrows attribute<cfprocresult> tag, 207<cfquery> tag, 68<cfsearch> tag, 156

memory, query caching, 76-77message attribute (<cfthrow> tag),107

messages (email), 140-141meta data, 268-269Method attribute (<cfhttp> tag), 138methods. See functions and methods

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 370

Page 394: ColdFusion MX Developer's Cookbook (Developer's Library)

371objects

Microsoft Security Bulletin, 337Microsoft SQL Server stored procedures

creating, 204-205parameters, 207-208

Mid() function, 11, 14migrating to ColdFusion MX,339-340

Migration Wizard, 339-340MIMEAttach attribute (<cfmail>tag), 140

MIN() function, 193Minute() function, 87MissingInclude exceptions, 104mode attribute (<cffile> tag),127-130, 133

Month() function, 87MonthAsString() function, 87moving files, 132-134multidimensional arrays, 44-45multiple exceptions, catching,104-105

multiple result sets (stored procedures), 213

Nname attribute

<cfapplication> tag, 92<cfargument> tag, 220<cfchart> tag, 115<cfdirectory> tag, 135<cffunction> tag, 219<cfhttp> tag, 138<cfobject> tag, 272<cfprocresult> tag, 207<cfsearch> tag, 156

name key, 269Name parameter (<cfquery> tag),68

nameConflict attribute (<cffile>tag), 130

naming structures, 52nested tags, 234-235.NET, invoking Web services with,312-314

Nielsen, Jakob (Web site), 332NonEmptyDirectoryCannotBeDeletedException, 136

noOutputAttribute() function, 223NoSuchTemplateException, 267null attribute (<cfprocparam> tag),211

Number data type, 284-286numeric data type, 219

Oobject attribute (<cfthrow> tag), 107Object exceptions, 104Object Management Group (OMG),278

objects. See also componentscharts, 113

administering with ColdFusionAdministrator, 123

chart containers, 114-116chart series, 117-118, 121click-through behaviors, 123creating, 113-114populating with query values, 121-122supported CFMX chart types,

118-120COM/DCOM objects, 276-277CORBA objects, 277-280creating, 271-273Date, 79-80DateTime, 79-80Java objects, 275-276methods, 273-274properties, 275

How can we make this index more useful? Email us at [email protected]

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 371

Page 395: ColdFusion MX Developer's Cookbook (Developer's Library)

372 objects

Time, 79-80XML objects

child elements, 300creating from other objects, 298creating with <cfxml> tag, 295-296creating with XmlElemNew() function,

296-298creating with XmlNew() function,

296-298element attributes, 298-300inner text, 300-301

oldFileSize key (cffile structure), 131OMG (Object Management Group),278

online resources. See Web sitesOpen Directory ColdFusionCategory Web site, 331

Open Directory Server-Side JavaCategory Web site, 331

Open WDDX Web site, 331operators

& (concatenation), 7-8AND, 186-187LIKE

% (percent symbol) wildcard, 196-197- (dash) wildcard, 198-199[] (brackets) wildcard, 198^ (caret) wildcard, 199-200_ (underscore) wildcard, 197-198

OR, 186-187table of, 186

OR operator, 186-187Oracle stored procedures, 205,208-209

ORDER BY statement, 187outfile argument (cfencode.exe), 236output attribute

<cffile> tag, 127-128<cffunction> tag, 219, 222-223<cfwddx> tag, 282

OUTPUT keyword, 211-212output parameters (stored procedures), 211-212

outputTrue() function, 223overriding functions, 267

PpaintStyle attribute (<cfchartseries>tag), 118

parameters. See attributesparsing

input forms, 34-35XML documents, 299

passing variables to stored procedures, 209-211

password attribute<cfftp> tag, 148<cfhttp> tag, 138<cfquery> tag, 68<cfstoredproc> tag, 207

path attribute<cfcollection> tag, 152<cfhttp> tag, 138

path key, 268pattern matching

excluded characters, 199-200groups of characters, 198range of characters, 198-199single characters, 197-198wildcard patterns, 196-197

percent symbol (%), 196-197period (.), 20pieSliceStyle attribute (<cfchart> tag), 115

pipe character (|), 21plus sign (+), 19POP servers, 140-141populating charts, 121-122Port attribute (<cfhttp> tag), 138Power() function, 223-225

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 372

Page 396: ColdFusion MX Developer's Cookbook (Developer's Library)

373queries

precision values (DateCompare()function), 83

prefixes (variables)client, 96-97session, 95-96

prepared statements, 200-202:print: character class, 22printing array contents, 344PrintVars.java listing, 320-321procedure attribute (<cfstoredproc>tag), 207

procedures, stored, 203-204addEmployee, 211-212calling, 206-207creating in Microsoft SQL Server,

204-205creating in Oracle, 205getDepartmentsAndProjects, 213giveRaise, 204-205multiple result sets, 213parameters

defining in Microsoft SQL Server,207-208

defining in Oracle, 208-209output parameters, 211-212passing, 209-211

passing variables to, 209-211processRequest() method, 241ProcessTagRequest() method, 247,249

programscom2java.exe, 277regsvr32, 276

projects table, 182properties. See attributesprotocols

FTPdownloading files, 148-149uploading files, 147-148

HTTP requests, 137-139

LDAP directoriesadding entries, 143-144deleting entries, 147entry attributes, 145-146querying, 141-143renaming entries, 146updating entries, 144-145

POP servers, 140-141SMTP servers, 140

ProxyPort attribute (<cfhttp> tag),139

ProxyServer attribute (<cfhttp>tag), 139

:punct: character class, 22

Qqualifiers, 30-31quantifiers, 19Quarter() function, 87queries. See also SQL statements

C++ CFX tags, 253-255caching, 76-77converting to lists, 75-76creating manually, 69-70creating with <cfquery> tag, 67-69displaying query results, 70-71functions

QueryAddColumn(), 70QueryAddRow(), 69-70QueryNew(), 69-70QuerySetCall(), 69-70QuotedValueList(), 75-76ValueList(), 75

in-memory queries, 73-74Java CFX tags, 245-247LDAP directories, 141-143populating charts with, 121-122prepared statements, 200-202query variables, 71-73

How can we make this index more useful? Email us at [email protected]

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 373

Page 397: ColdFusion MX Developer's Cookbook (Developer's Library)

374 query attribute

query attribute<cfchartseries> tag, 118<cfindex> tag, 153

query data type, 219, 284-285Query interface, 246QueryAddColumn() function, 70QueryAddRow() function, 69-70QueryNew() function, 69-70QuerySetCall() function, 69-70question mark (?), 19QuotedValueList() function, 75-76

R/r argument (cfencode.exe), 236ranges of characters

excluding, 199-200matching, 198-199

reading files, 15, 125-126receiving email, 140-141recordCount variable, 72recordSearched attribute (queryobjects), 157

RecordSet class, 294recurse attribute (<cfindex> tag),153

recursive functions, 223-225Redirect attribute (<cfhttp> tag),139

redirecting requests to servlets/JSPs,318

references to functions, 225-227REFind() function, 18-19registering

C++ CFX tags, 257-258DLLs (Dynamic Link Libraries), 276Java CFX tags, 256

Registry, 97-98regsvr32 program, 276remote function, 315

remotefile attribute (<cfftp> tag),148-149

RemoveChars() function, 11removing directories, 136renaming

directories, 136files, 132-134LDAP directories, 146

Replace() function, 11, 17-18ReplaceNoCase() function, 11, 17-18replacing substrings, 17-18Request interface, 243requests (HTTP), 137-139required attribute (<cfargument>tag), 220

ResolveURL attribute (<cfhttp>tag), 139

Response interface, 241result sets

displaying, 70-71sorting, 187stored procedures, 213

resultset attribute (<cfprocresult>tag), 207

reThrowException() method, 249rethrowing exceptions, 108-109return values (functions), 222returncode attribute (<cfstoredproc> tag), 207

returning custom tag results,231-232

returntype attribute (<cffunction>tag), 219, 309

RIGHT OUTER JOIN statement,191

Right() function, 10-11role table (authentication application), 176

roles (user), 163roles attribute (<cffunction> tag),219

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 374

Page 398: ColdFusion MX Developer's Cookbook (Developer's Library)

375selecting data

rotated attribute (<cfchart> tag),115

rowsadding, 183aliases, 187-188deleting, 184updating, 183-184

RTrim() function, 11

Ssandbox security, 337scale attribute (<cfprocparam> tag),211

scaleFrom attribute (<cfchart> tag),116

scaleTo attribute (<cfchart> tag),116

scope (application), 92-94score attribute (query objects), 157scripts (CFML)

<cfscript> tag, 341-343exception handling, 346-347if-then-else statements, 343loops, 343-345switch statements, 345-346

search engines,Verityadding data to collections, 152-155case sensitivity, 157creating collections, 151-152explicit searches, 157simple searches, 155-157Web site, 151

SearchEngine exceptions, 105searching

lists, 29-30strings

Find() function, 16-17FindNoCase() function, 16-17REFind() function, 18-19

Verity collections, 155-157XML documents, 301-302

Second() function, 87Secret Agents Web site, 331Section 508 Web site, 332Secure Socket Layer (SSL), 333security

authentication and authorization, 159authentication example, 165-176authentication realm, 159blocks of code, 162-163functions, 164j_password field, 161-162j_username field, 161-162logins, 160logouts, 160-161user IDs, 162user roles, 163

cross-site scripting, 336-337DOS (denial of service) attacks,

335-336encryption, 12-13file uploading, 335sandbox security, 337Security exceptions, 104SecurityFocus Vulnerability Database

Web site, 338session hijacking, 333-334SSL (Secure Socket Layer), 333URL injection hacking, 334-335Web sites, 337-338

Security exceptions, 104SecurityFocus Vulnerability DatabaseWeb site, 338

SELECT statement, 185selecting data

limiting rows returned, 185-186multiple conditions, 186-187multiple tables, 188-189

How can we make this index more useful? Email us at [email protected]

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 375

Page 399: ColdFusion MX Developer's Cookbook (Developer's Library)

376 selecting data

pattern matchingexcluded characters, 199-200groups of characters, 198range of characters, 198-199single characters, 197-198wildcard patterns, 196-197

sorting results, 187unique values, 192Web form check boxes, 195-196

sendingemail, 140HTTP requests, 137-139

series objectsmanaging, 117-118populating with explicit values, 121

seriesColor attribute (<cfchartseries> tag), 118

seriesLabel attribute (<cfchartseries> tag), 118

seriesPlacement attribute (<cfchart> tag), 116

server attribute<cfldap> tag, 148<cfobject> tag, 273

server-side forwarding, 318serverDirectory key (cffile structure), 132

serverFile key (cffile structure), 132ServerFileExt attribute (<cffile> tag), 335

serversApache, 315-316FTP servers

downloading files, 148-149uploading files, 147-148

POP servers, 140-141SMTP servers, 140

services (Web), 305creating, 308-309data types, 309-311deploying, 311

DogService, 312-314instances of, 307-308invoking with .NET, 312-314invoking with <cfinvoke> tag,

306-307invoking with Java, 315-316TravelService, 309-310

servletsaccessing ColdFusion pages from, 319data sharing, 320-322forwarding requests to, 318including, 318-319

session hijacking, 333-334Session Management, 95-96session prefix, 95-96sessionManagement attribute(<cfapplication> tag), 92-93

sessionTimeout attribute (<cfapplication> tag), 92

SET statement, 183-184setClientCookies attribute (<cfapplication> tag), 92-93

setData() method, 246-247, 255setDomainCookies attribute (<cfapplication> tag), 92

setField() method, 294Settings Migration Wizard, 339-340setVariable() method, 244-245,249-253

Setvars.cfm listing, 320sharing data between ColdFusionand servlets/JSPs, 320-322

show3d attribute (<cfchart> tag),116

showBorder attribute (<cfchart> tag), 116

showLegend attribute (<cfchart> tag), 116

showMarkers attribute (<cfchart> tag), 116

showXGridlines attribute (<cfchart> tag), 116

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 376

Page 400: ColdFusion MX Developer's Cookbook (Developer's Library)

377statements

showYGridlines attribute (<cfchart> tag), 116

simple Verity searches, 155-157SimpleAuthenticator.cfm file, 168sizing arrays, 38SMTP servers, 140sort attribute (<cfdirectory> tag),135

sortingarrays, 41-44lists, 30result sets, 187structures, 63-66

sortOrder argument (StructSort()function), 64

sortType argument (StructSort()function), 64

sortXAxis attribute (<cfchart> tag),116

source attribute (<cffile> tag), 133:space: character class, 22Split() function, 221SQL Server stored procedures

creating, 204-205parameters, 207-208

SQL statements, 181-182aggregate functions, 192-193AND operator, 186-187, 205AS, 187-188CREATE OR REPLACE, 205CREATE PROCEDURE, 204-205DELETE, 184DISTINCT, 192FROM, 188-189FULL OUTER JOIN, 191GROUP BY, 193HAVING, 194IN, 194-196, 209INSERT INTO, 183LEFT OUTER JOIN, 191

LIKE operator[] (brackets) wildcard, 198^ (caret) wildcard, 199-200- (dash) wildcard, 198-199% (percent symbol) wildcard, 196-197_ (underscore) wildcard, 197-198

OR operator, 186-187ORDER BY, 187prepared statements, 200-202RIGHT OUTER JOIN, 191SELECT, 185SET, 183-184UPDATE, 183-184VALUES, 183WHERE, 185-186, 189-190

SSL (Secure Socket Layer), 333start tags, 232-233startRow attribute (<cfsearch> tag),156

state informationstoring in database, 99-100storing in Registry, 97-98storing with cookies, 98-99

statements, 181-182aggregate functions, 192-193AND operator, 186-187, 205AS, 187-188assignment statements, 342break, 345catch, 346-347CFScript, 341continue, 345CREATE OR REPLACE, 205CREATE PROCEDURE, 204-205DELETE, 184DISTINCT, 192FROM, 188-189FULL OUTER JOIN, 191function-call statements, 343GROUP BY, 193

How can we make this index more useful? Email us at [email protected]

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 377

Page 401: ColdFusion MX Developer's Cookbook (Developer's Library)

378 statements

HAVING, 194if-then-else, 343IN, 194-196, 209INSERT INTO, 183LEFT OUTER JOIN, 191LIKE operator

[] (brackets) wildcard, 198^ (caret) wildcard, 199-200- (dash) wildcard, 198-199% (percent symbol) wildcard, 196-197_ (underscore) wildcard, 197-198

OR operator, 186-187ORDER BY, 187prepared statements, 200-202RIGHT OUTER JOIN, 191SELECT, 185SET, 183-184switch, 345-346try, 346-347UPDATE, 183-184VALUES, 183WHERE, 185-186, 189-190

stored procedures, 203-204addEmployee, 211-212calling, 206-207creating in Microsoft SQL Server,

204-205creating in Oracle, 205getDepartmentsAndProjects, 213giveRaise, 204-205multiple result sets, 213parameters

defining in Microsoft SQL Server,207-208

defining in Oracle, 208-209output parameters, 211-212passing, 209-211

passing variables to, 209-211

storing client state informationwith cookies, 98-99in database, 99-100in Registry, 97-98

string data type, 218, 284-286strings, 7

ASCII character codes, 9brackets ([]), 20-21character classes, 22concatenating, 7-8decrypting, 12-13delimiting, 8encrypting, 12-13escape characters, 21-22hashing, 13-14looping over, 14-15OR operations, 21quantifiers, 19searching

Find() function, 16-17FindNoCase() function, 16-17REFind() function, 18-19

substringscreating, 10-11finding, 18-19replacing, 17-18substring functions, 11-12

wildcards, 20StripCR() function, 12struct data type, 219StructAppend() function, 53-54StructClear() function, 54StructCopy() function, 54, 61-63StructCount() function, 53StructFind() function, 54, 57StructFindKey() function, 61StructFindValue() function, 61StructGet() function, 61StructInsert() function, 54-56

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 378

Page 402: ColdFusion MX Developer's Cookbook (Developer's Library)

379tables

StructIsEmpty() function, 52-53StructKeyArray() function, 61StructKeyExists() function, 52-53StructKeyList() function, 61StructKeyLists() function, 52, 59-60StructNew() function, 52-54StructSort() function, 54, 63-66StructUpdate() function, 54-56Structure argument (StructSort() function), 64

Structure data type, 284-286Structured Query Language.

See SQL statementsstructureReference argument(StructSort() function), 64

structures, 51Attributes, 230-231cffile, 131-132conversions

CFML to WDDX, 281-283Java to WDDX, 290-292WDDX to CFML, 285-286WDDX to Java, 292-294WDDX to JavaScript, 286-287

copying, 61-63creating, 52dot notation, 58-59information functions, 52-53inserting values into, 55-56key names, 57looping over, 59-60management functions, 53-55naming, 52sorting, 63-66ThisTag, 233updating values in, 56-57utility functions, 60-61

subject attribute (<cfmail> tag), 140

substringscreating, 10-11finding, 18-19replacing, 17-18substring functions, 11-12

SUM() function, 193summary attribute (query objects),157

Sun Microsystems Java Web site, 331SuperSplit() function, 221suppressing function output, 222-223swapping array values, 48switch statements, 345-346syndicated content (WDDX),287-290

Ttables

adding rows to, 183aggregate functions, 192-194aliases, 187-188authentication application, 175-176CDATA, 99CGLOBAL, 100deleting rows from, 184department, 182employees, 181-182employee_projects, 182grouping data in, 190-193joining, 189-191pattern matching

excluded characters, 199-200groups of characters, 198range of characters, 198-199single characters, 197-198wildcard patterns, 196-197

projects, 182

How can we make this index more useful? Email us at [email protected]

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 379

Page 403: ColdFusion MX Developer's Cookbook (Developer's Library)

380 tables

selecting data inlimiting rows returned, 185-186multiple conditions, 186-187multiple tables, 188-189sorting results, 187unique values, 192Web form check boxes, 195-196

updating, 183-184tags

C++ CFX tags, 239attributes, 250-251<CFX_GetMemoryStatus>,

251-253<CFX_ReverseQuery>, 253-255<CFX_SubString>, 250-251<CFX_WriteMemoryStatus>,

247-248ColdFusion variables, 251-253creating, 247-249installing, 257-258queries, 253-255registering, 257-258

<cfapplication>, 91-93, 97-99<cfargument>, 220-221<cfcatch>, 102-105<cfchart>, 113-116, 122-123<cfchartdata>, 113-114, 121<cfchartseries>, 113-114, 117-118<cfcollection>, 151-152<cfcomponent>, 259-261

displayname attribute, 261extends attribute, 265-267hint attribute, 261

<cfdirectory>, 134-136<cfdump>, 307<cffile>, 15

accept attribute, 335append action, 127-128attributes, 126-130, 133copy action, 134

delete action, 134move action, 133read action, 125-126rename action, 133-134ServerFileExt attribute, 335upload action, 129-132write action, 126-127writing files, 126

<cfftp>, 147-149<cffunction>, 164, 218-219, 222-223,

259-261, 309<cfheader>, 288<cfimport>, 237-238<cfinclude>, 174<cfindex>, 152-153<cfinvoke>, 263-264, 306-307<cfinvokeargument>, 264<cfldap>, 141-147<cflogin>, 160, 177<cfloginuser>, 160<cflogout>, 160-161<cfloop>, 14-15, 31-35, 70-71<cfmail>, 140<cfmodule>, 236-237<cfobject>, 262-263, 271-273,

276-277, 307-308action attribute, 272argumentcollection attribute, 264class attribute, 272component attribute, 262, 264, 273context attribute, 273locale attribute, 273name attribute, 272server attribute, 273type attribute, 272webservice attribute, 273

<cfoutput>, 39-40, 70-71, 190-191<cfpop>, 140-141<cfprocparam>, 209-211<cfprocresult>, 206-207, 213

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 380

Page 404: ColdFusion MX Developer's Cookbook (Developer's Library)

381Time objects

<cfproperty>, 309-310<cfquery>, 67-69

blockFactor parameter, 68cachedAfter parameter, 68, 76-77cachedWithin parameter, 68, 76-77Datasource parameter, 68, 73-74dbType parameter, 68, 73-74Debug parameter, 68example, 67maxRows parameter, 68Name parameter, 68parameters, 68Password parameter, 68Timeout parameter, 68Username parameter, 68

<cfqueryparam>, 200-201, 334<cfrethrow>, 108-109<cfreturn>, 222<cfscript>, 341-343<cfsearch>, 155-157<cfset>, 94<cfsetting>, 288<cfstoredproc>, 206-207<cfthrow>, 107-108<cftry>, 102-104<cfwddx>, 281-283

CFML2JS action, 283-284CFML2WDDX action, 281-283WDDX2CFML action, 285-286WDDX2JS action, 286-287

<cfxml>, 295-296converting to scripts

<cfscript> tag, 341-343exception handling, 346-347if-then-else statements, 343loops, 343-345switch statements, 345-346

custom tagsaccessing, 230attributes, 230-231

biu.cfm, 232calling regardless of location, 236-237<cfimport> tag, 237-238<cfmodule> tag, 236-237creating, 229-230encoding, 235-236getDomainTag.cfm, 231greetingTag.cfm, 230helloWorldTag.cfm, 229-230importing, 237-238mailto.cfm, 234nested tags, 234-235return results, 231-232start/end tags, 232-233

<http>, 137-139Java CFX tags, 239

attributes, 241-243<CFX_GetMemoryStatus>,

244-245<CFX_ReverseQuery>, 245-246<CFX_SubString>, 242<CFX_WriteMemoryStatus>,

240-241ColdFusion variables, 244-245creating, 240-241CustomTag interface, 240installing, 256queries, 245-247registering, 256

migrating to ColdFusion MX, 340Template exceptions, 104text. See lists; stringsTextQualifier attribute (<cfhttp> tag), 139

ThisTag variable, 233throwException() method, 249throwing exceptions, 107-108ThrowOnError attribute (<cfhttp> tag), 139

Time objects, 79-80

How can we make this index more useful? Email us at [email protected]

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 381

Page 405: ColdFusion MX Developer's Cookbook (Developer's Library)

382 time spans

time spans, 85-86timeCreated key (cffile structure),132

TimeFormat() function, 84-85timeLastModified key (cffile structure), 132

Timeout attribute (<cfhttp> tag), 139

Timeout parameter (<cfquery> tag), 68

times/datescomparing, 82-83date formatting, 80-82date information functions, 86-87Date objects, 79-80DateTime objects, 79-80determining time differences, 83-84functions

CreateDate(), 80CreateDateTime(), 80CreateTime(), 80CreateTimeSpan(), 85-86DateCompare(), 82-83DateDiff(), 83-84DateFormat(), 80-82Day(), 87DayOfWeek(), 87DayOfWeekAsString(), 87DayOfYear(), 87DaysInMonth(), 87DaysInYear(), 87FirstDayOfMonth(), 87Hour(), 87IsLeapYear(), 87LSDateFormat(), 88LSTimeFormat(), 88Minute(), 87Month(), 87MonthAsString(), 87Quarter(), 87

Second(), 87TimeFormat(), 84-85Week(), 87Year(), 87

locale-specific dates/times, 88time formatting, 84-85Time objects, 79-80time spans, 85-86

tipBGColor attribute (<cfchart>tag), 116

tipStyle attribute (<cfchart> tag),116

title attribute (query objects), 157to attribute (<cfmail> tag), 140ToBase64() function, 126tools

Compatibility Analyzer, 339Settings Migration Wizard, 339-340

toplevelvariable attribute (<cfwddx> tag), 282

transformationss, 302-304TravelService Web service, 309-310Trim() function, 12, 26try statements, 346-347type attribute

<cfargument> tag, 220<cfchartseries> tag, 118<cfindex> tag, 153<cfmail> tag, 140<cfobject> tag, 272<cfprocparam> tag, 210<cfsearch> tag, 156<cfthrow> tag, 107

type key, 268types. See data types

UUDFs. See user-defined functionsunderscore (_), 197-198

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 382

Page 406: ColdFusion MX Developer's Cookbook (Developer's Library)

383variable attribute

unique values, selecting, 192UPDATE statement, 183-184updating

LDAP directories, 144-145tables, 183-184values in structures, 56-57

uploading files, 129-132, 147-148,335

:upper: character class, 22url attribute

<cfchart> tag, 116, 122-123<cfhttp> tag, 138query objects, 157

URL injection hacking, 334-335urlPath attribute (<cfindex> tag),153

useit.com Web site, 332user-defined functions, 217

arguments, 220-221data types, 218-219declaring, 218-219recursive functions, 223-225references, 225-227return values, 222suppressing output, 222-223

user_roles table (authenticationapplication), 176

user table (authentication applica-tion), 175

user.cfm file, 167UserAgent attribute (<cfhttp> tag),139

username attribute<cfftp> tag, 148<cfhttp> tag, 138<cfquery> tag, 68<cfstoredproc> tag, 207

usersauthentication and authorization

authentication example, 165-176

authentication realm, 159blocks of code, 162-163functions, 164j_password field, 161-162j_username field, 161-162logins, 160logouts, 160-161user IDs, 162user roles, 163

logging in, 160logging out, 160-161user IDs, 162

usetimezoneinfo attribute(<cfwddx> tag), 282

utility functions (arrays), 47-48uuid data type, 219

V/v argument (cfencode.exe), 236validate attribute (<cfwddx> tag),282

value attribute (<cfprocparam>tag), 210

valueColumn attribute (<cfchartseries> tag), 118

ValueList() function, 75values

list valueschanging, 28-29empty values, 26-28

structure valuesdisplaying, 57inserting, 55-56key names, 57updating, 56-57

VALUES statement, 183variable attribute

<cffile> tag, 126<cfprocparam> tag, 210

How can we make this index more useful? Email us at [email protected]

36 0672324628 Index-fix2 6/8/05 11:11 AM Page 383