323 30 9MB
English Pages 616 [641] Year 2010;2011
ADOBE
®
COLDFUSION 9 ®
Getting Started
web application construction kit VOLUME 3
Ben Forta and Raymond Camden with Josh Adams, Charlie Arehart, Jeffrey Bouley, Ken Fricklas, Alan Rother, Sarge Sargent, and Matt Tatam
Adobe ColdFusion 9 Web Application Construction Kit, Volume 3: Advanced Application Development Ben Forta and Raymond Camden with Josh Adams, Charlie Arehart, Jeffrey Bouley, Ken Fricklas, Alan Rother, Sarge Sargent, and Matt Tatam This Adobe Press book is published by Peachpit. For information on Adobe Press books, contact: Peachpit 1249 Eighth Street Berkeley, CA 94710 510/524-2178 510/524-2221 (fax) For the latest on Adobe Press books, go to www.adobepress.com To report errors, please send a note to [email protected] Peachpit is a division of Pearson Education Copyright © 2011 by Ben Forta Series Editors: Rebecca Freed and Karen Reichstein Editor: Judy Ziajka Technical Reviewer: Terry Ryan Production Editor: Tracey Croom Compositor: Maureen Forys, Happenstance Type-O-Rama Proofreader: Liz Welch Indexer: Ron Strauss Cover design: Charlene Charles-Will NOTICE OF RIGHTS
All rights reserved. No part of this book may be reproduced or transmitted in any form by any means, electronic, mechanical, photocopying, recording, or otherwise, without the prior written permission of the publisher. For information on getting permission for reprints and excerpts, contact [email protected]. NOTICE OF LIABILITY
The information in this book is distributed on an “As Is” basis, without warranty. While every precaution has been taken in the preparation of the book, neither the authors nor Peachpit shall have any liability to any person or entity with respect to any loss or damage caused or alleged to be caused directly or indirectly by the instructions contained in this book or by the computer software and hardware products described in it. TRADEMARKS
Adobe, ColdFusion, ColdFusion Builder, Dreamweaver, Flash, Flash Builder, Flex, and LiveCycle are trademarks or registered trademarks of Adobe Systems, Inc., in the United States and/or other countries. All other trademarks are the property of their respective owners. Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and Peachpit was aware of a trademark claim, the designations appear as requested by the owner of the trademark. All other product names and services identified throughout this book are used in editorial fashion only and for the benefit of such companies with no intention of infringement of the trademark. No such use, or the use of any trade name, is intended to convey endorsement or other affiliation with this book. ISBN 13: 978-0-321-67920-8 ISBN 10: 0-321-67920-2
9`f^iXg_`\j 9\e=fikX Ben Forta is director of platform evangelism for Adobe Systems Incorporated and has more than two decades of experience in the computer software industry in product development, support, training, and marketing. Ben is the author of the best-selling ColdFusion book of all time, Adobe ColdFusion Web Application Construction Kit, as well as books on SQL, JaveServer Pages, Windows development, Regular Expressions, and more. More than half a million Ben Forta books have been printed in more than a dozen languages worldwide. Ben helped create the official Adobe ColdFusion training material, as well as the certification tests and study guides for those tests. He writes regular columns on ColdFusion and Internet development and spends a considerable amount of time lecturing and speaking on application development worldwide. Ben welcomes your email at WZc5[dgiV#Xdb and invites you to visit his Web site at ]iie/$$[dgiV#Xdb / and his blog at ]iie/$$[dgiV#Xdb$Wad\.
IXp:Xd[\e Raymond Camden is a software consultant focusing on ColdFusion and RIA development. A longtime ColdFusion user, Raymond has worked on numerous ColdFusion books, including Adobe ColdFusion Web Application Construction Kit, and has contributed to the Fusion Authority Quarterly Update and the ColdFusion Developers Journal. He also presents at conferences and contributes to online webzines. He founded many community Web sites, including CFLib.org, ColdFusionPortal.org, and ColdFusionCookbook.org, and is the author of open source applications, including the popular BlogCFC (lll#Wad\X[X#Xdb) blogging application. Raymond is an Adobe Community Professional. He is the happily married proud father of three kids and is somewhat of a Star Wars nut. Raymond can be reached at his blog (lll#XdaY[jh^dc_ZY^#Xdb) or via email at gVn5XVbYZc[Vb^an#Xdb.
:_Xic`\8i\_Xik A veteran ColdFusion developer and troubleshooter since 1997 with more than 25 years in IT, Charlie Arehart is a longtime contributor to the ColdFusion community and a recognized Adobe Community Professional. As an independent consultant, he provides short-term troubleshooting and tuning assistance and training and mentoring for organizations of all sizes and ColdFusion experience levels (XVgZ]Vgi#dg\$Xdchjai^c\). Besides running the 2000-member Online ColdFusion Meetup (coldfusionmeetup.com, an online CF user group), he hosts the UGTV repository of recorded presentations from hundreds of speakers (XVgZ]Vgi#dg\$j\ik) and the CF411 site with more than 1000 tools and resources for ColdFusion developers (cf411.com). A certified Advanced ColdFusion Developer and an instructor for each version since ColdFusion 4, Charlie has spoken at each of the major ColdFusion conferences worldwide and is a contributor to all three volumes of Adobe ColdFusion 9 Web Application Construction Kit.
A\]]i\p9flc\p Jeffrey is director of consulting services at Universal Mind, Inc. He has 16 years of experience in information technology, working on several fronts, from sales to delivery. He has had the opportunity to work with organizations such as NASA, Houghton Mifflin, Accenture, Johnson & Johnson, Bancolombia, Macromedia, Allaire, Quest Technologies Inc., Lockheed Martin, Perot Systems, and AT&T. His technical knowledge covers the back-end databases Oracle 7 through 10 and Microsoft SQL Server 7 through 2005 as well as programming with Flex (ActionScript), ColdFusion, Java, C#, VB.Net, Flash, Active Server pages, Visual Basic (using COM), and ESRI. Jeff enjoys facilitating projects he manages with Agile/SCRUM. Jeffrey earned his master’s degree in management of technology from the University of Miami and holds a bachelor’s degree in information systems from the University of Central Florida.
B\e=i`ZbcXj Ken Fricklas is a long-time ColdFusion author, speaker, and trainer, having used ColdFusion beginning with a slim binder called ColdFusion 1.5. He’s co-founder of several Internet companies, including Mallfinder Network. He lives with his wife and son in Boulder, Colorado, and in his spare time occasionally performs improvisational comedy, listens to and performs music, and enjoys the Colorado mountains on foot and bicycle.
8cXeIfk_\i Alan Rother currently serves as the director of engineering for Interactive Sites, a leading custom software development firm for the hospitality industry, specializing in content management systems, group business products, and custom systems integration solutions. Alan began working with ColdFusion shortly after graduating from The University of Arizona in late 1999. He is a certified ColdFusion programmer and currently acts as the manager of the Phoenix ColdFusion Users Group in Arizona (lll#VoX[j\#dg\). He can be contacted on his blog (VaVc#gdi]Zg[Vb^an# cZi) or on Twitter (56aVcGdi]Zg).
JXi^\JXi^\ek Sarge is a former senior product support engineer for ColdFusion and JRun with Adobe’s North American Customer Care organization. During his tenure with Allaire, Macromedia, and now Adobe, he has also supported Breeze/Connect, Contribute Publishing Services, and Flex. He is well-known in the ColdFusion community as an expert in configuration, optimization, scalability, security, and LDAP integration. A Certified ColdFusion Developer and MCSE, he has served as contributor and technical editor or reviewer for several ColdFusion books, written several Developer Connection and Knowledgebase articles for the Adobe Web site, and spoken at several conferences and user groups. Sarge is currently Adobe’s technical account manager for Flash and Flash Media Server. Although his focus is now on serving the Adobe Flash platform community, ColdFusion will forever remain in his blood. Sarge continues to share his onion on his blog at lll#hVg\ZlVn#Xdb.
DXkkKXkXd Matt Tatam has been developing and instructing in ColdFusion for more than 14 years. He has published articles and books on a number of Adobe technologies.
8Zbefnc\[^d\ekj 9\e=fikX Thanks to my co-authors, Ray Camden and Charlie Arehart for their outstanding contributions. Although this book is affectionately known to thousands as “the Ben Forta book,” it is, in truth, as much theirs as it is mine. An extra thank you to Ray Camden for once again bravely accepting the role of lead co-author. Thanks to fellow Adobe Platform Evangelist Terry Ryan for his thorough technical review. Thanks to Nancy Ruenzel and the crew at Peachpit for allowing me the creative freedom to build these books as I see fit. Thanks to Karen Reichstein and Rebecca Freed for bravely stepping in as series editors on this revision, and to Judy Ziajka for so ably shepherding this book through the publication process yet again. Thanks to the thousands of you who write to me with comments, suggestions, and criticism (thankfully not too much of the latter)— I do read each and every message (and even attempt to reply to them all, eventually), and all are appreciated. And last, but by no means least, a loving thank you to my wife Marcy and our children for putting up with (and allowing) my often hectic work schedule. Their love and support make all that I do possible.
IXp:Xd[\e I’d like to thank Ben and Adobe Press for once again asking me to be a part of this incredible series. It is both an honor and a privilege! I’d also like to thank Adobe, specifically Adam Lehman and the engineers. Thanks for having me as part of the ColdFusion 9 beta process and allowing me to help shape the product I love. I promise I’ll ask only half as many annoying questions for ColdFusion 10.
:_Xic`\8i\_Xik First, I want to thank Ben for having me as a contributor to this series. With so many excellent authors among the current and past contributors, I really feel privileged. I also want to thank him for all his contributions to the community. Again, as with my fellow authors, I follow in the footsteps of giants. In that regard, I want to acknowledge the awesome ColdFusion community. I’ve so enjoyed being a part of it, as both beneficiary and contributor, since 1997. This book’s for you.
A\]]i\p9flc\p Many thanks to Ben for including me again in the delivery of a book supporting an incredible product. It never ceases to amaze me how ColdFusion continues to provide companies and the developers who work with it a path to success.
B\e=i`ZbcXj I’d like to thank my wife Carolyn, my son Bryce, and Ben Forta and all the folks at Adobe Press for their patience. I’d also like to thank all my employees and employers over the years for putting up with me.
8cXeIfk_\i First and foremost I want to thank Ben for giving me the opportunity to contribute to this project, it’s been a really great experience. Sarge, thank you for putting in a good word for me with Ben, and thank you John Bland for encouraging me through the process. Caroline, Blayter, and Nate, thank you for all of your help and support over the years. And to “the boys,” thank you for giving me the time to work on this project and for all of your support for the ColdFusion community.
JXi^\JXi^\ek Thanks to Ben for having me on the project again. Special thanks to my family for being a rock and a refuge for me. Xtra-special thanks to my wife Nicole for granting me permission to work on this project and for being my “Ambassador of Quon.” Bob!
;\[`ZXk`fej 9\e=fikX Dedicated to the ColdFusion community, a loyal and passionate group that I’ve been proud to call my friends for a decade and a half.
IXp:Xd[\e As always, for my wife. Thank you, Jeanne, for your love and support.
:_Xic`\8i\_Xik I’d like to dedicate this book to my wife of 10 years and the love of my life, Kim. I couldn’t do all I do without your patience, support, and encouragement. Thank you, my love. God truly blessed me when He brought you into my life.
A\]]i\p9flc\p I dedicate this book to my wife Shannon and 2-year-old sons Brennon and Brodie; you supply an incredible richness to my life, a richness that motivates me to be the best I can.
8cXeIfk_\i This book and everything I do is of course dedicated to my amazing wife Amanda and our wonderful daughter Adisyn; I wouldn’t be anywhere without your love and support.
JXi^\JXi^\ek As always, I dedicate my work to my fam.
DXkkKXkXd To my family, who remind me daily, what really matters in life.
:FEKC8E:< Introduction G8IK0 :i\Xk`e^?`^_$8mX`cXY`c`kp8ggc`ZXk`fej
xix (
:?8GKc[dºYViVhdjgXZ2¹YWTJi^a^inº3 H:A:8I^ciTjhZg^Y!kXTjhZgcVbZ!kXTeVhhldgY!kXTZbV^a!YiTXgZViZYViZ;GDBiWaTJhZg L=:G:kXTcVbZ2»jhZgCVbZ¼ 1$X[fjZgn3 =ZgZ^hi]Z^c[dgbVi^dcndjgZfjZhiZY/1Wg3 1X[djiejifjZgn2¹\ZiJhZg>c[dº3 NdjgJhZg>9/^ciTjhZg^Y1Wg3 NdjgJhZgCVbZ/kXTjhZgcVbZ1Wg3 NdjgEVhhldgY/kXTeVhhldgY1Wg3 Ndjg:bV^a/kXTZbV^a1Wg3 9ViZndj_d^cZY/YiTXgZViZYViZ 1$X[djieji3
As you can see, only one query need be called to return this data. This is a common mistake.
8Yjfclk\GXk_#I\cXk`m\GXk_#Xe[Fk_\iC`ebj One of the more common problems when working with ColdFusion is confusion about when to use the absolute or relative path for a link. Both methods can be employed, but you must be
55
56
CHAPTER
48
Scaling with ColdFusion
cognizant of the impact of each approach when you are coding for a clustered environment. Here are a couple of questions to ask before utilizing absolute or relatives paths in your application: N
Will the link be moved at any point in time? If the answer is yes, an absolute path will be a more viable option, since it is assumed that the new path can be mapped on the Web server to be the same mapping as before.
N
Does the path exist under the current subdirectory? If the answer is yes, then relative path mapping will work.
EFK
C;Q_gjc#mba. Make sure that the entry for the ProxyService YZVXi^kViZY attribute is set to [VahZ! like this: 1Viig^WjiZcVbZ2ºYZVXi^kViZYº3[VahZ1$Viig^WjiZ3
11. You can now test to see if your cluster is working correctly. If your server is up and running and you want to take it out of the cluster for maintenance, you can remove the instance(s) for that server from the cluster via the ColdFusion 9 Administrator. When you’re finished with maintenance, you can add the instance(s) back in. Or, if you want to add more ColdFusion 9 servers to the cluster, add them via the ColdFusion 9 Administrator. Nothing could be simpler. K@G
PfldXpefk`Z\k_Xk:fc[=lj`fe0Xccfnjpflkfn\`^_k:fc[=lj`fej\im\ij]fij`klXk`fejn_\i\pfl_Xm\jpjk\djn`k_[`]]\i\ek i\jfliZ\jÇjlZ_Xjfe\j\im\ik_Xk_Xj]fli:GLjXe[+>9f]d\dfip#ZfdgXi\[n`k_Xj\im\ik_Xk_Xjknf:GLjXe[fe\^`^f] [XkX%PflZXe^`m\k_\]fli$:GLj\im\iX_`^_\in\`^_k#n_`Z_n`ccdXb\k_\:fc[=lj`fe0CfX[9XcXeZ\ii\]\iXcXi^\g\iZ\ekX^\ f]j\im\ii\hl\jkjkfk_Xkj\im\i%
?Xi[nXi\CfX[$9XcXeZ`e^Fgk`fej Hardware load balancing, similar to software balancing with ColdFusion 9 Load Balancing, manages traffic within a Web cluster according to a specified load-balancing algorithm (such as roundrobin, or least connections). However, unlike ColdFusion 9 Load Balancing, hardware-based load-balancing devices sit in front of the Web cluster, meaning that all traffic destined for the Web cluster must pass through the load-balancing device.
Hardware Load-Balancing Options
Suppose you are configuring a hardware load balancer to load-balance the lll#bnXdbeVcn#Xdb domain, which contains three Web servers and a database server. You would configure the load balancer with the IP address that corresponds, DNS-wise, to lll#bnXdbeVcn#Xdb. This address is called the virtual Web server address. On the load balancer, you would also configure the addresses of the three Web servers behind the load balancer and a load-balancing algorithm, such as least connections. The load balancer would assign users to the server with the least load. Figure 48.10 illustrates the basic network configuration of the load balancer. =`^li\+/%(' The load balancer contains the virtual Web server lll#
K_\@ek\ie\k
bnXdbeVcn#Xdb
directing traffic to three clustered servers. =`i\nXcc
CfX[9XcXeZ\i n`k_?fkJgXi\
N\Y'(
N\Y')
N\Y'*
EFK
9 and 8;ID@:C as session-based cookies may appease users who are filtering cookies. Session-based cookies offer an alternative and are not persistent, existing only as long as the user session exists. Listing 50.4 illustrates how to code this work-around. By setting the client cookie attribute to Cd, ColdFusion does not automatically store the variables to cookies; you need to set them manually in code. Make changes to 6eea^XVi^dc#X[b as seen in Listing 50.4. in the 6eea^XVi^dc#X[b template. C`jk`e^,'%+ 6eea^XVi^dc#X[b —Settings for Client Management with Session-Based Cookies 1X[Veea^XVi^dccVbZ2ºBMjhZghº Xa^ZcibVcV\ZbZci2ºNZhº hZiXa^ZciXdd`^Zh2ºCdº3 1""HZii]ZXa^ZciXdd`^ZhVhhZhh^dc"WVhZYXdd`^Zh""3 1X[Xdd`^ZcVbZ2ºXÄYºkVajZ2º8A>:CI#XÄYº3 1X[Xdd`^ZcVbZ2ºX[id`ZcºkVajZ2º8A>:CI#X[id`Zcº3
You can use the client management methods described previously to manage session variables as well, except that you can’t store session variables in a central database.
B\\g`e^k_\Lj\ifek_\JXd\DXZ_`e\ One popular method for managing session state in a scaled environment is to direct a user to the server that’s currently most available (as in least utilized) and to have the user continue to interact with the same server for the duration of the session. You can accomplish this approach through either a software-based solution session-aware clustering or hardware-based solutions. EFK
9 and 8;ID@:C or some other unique identifier. Because client variables can persist from session to session, you now have a collection of information for each user that can be accessed whenever the user visits your site. Given the simplicity of such a setup, this is a good strategy for many applications—it anticipates the need to scale across multiple servers, even if you don’t need to do so right away. EFK
9Xe[8;ID@:Clj`e^fe\f]k_\d\k_f[j[\jZi`Y\[\Xic`\i`eÈ:fiXA;9:[XkXjfliZ\%Lj`e^XZc`\ek$j\im\i[XkXYXj\]fik_\Z\ekiXc[XkXYXj\`jgi\]\ii\[%
2. On all your ColdFusion servers, create a data source in ColdFusion Administrator pointing to that central database. 3. In the ColdFusion Administrator, select Client Variables in the Server Settings section. 4. Choose the data source from the pull-down menu and click the Add button. 5. On the next screen, check the Create Client Database Tables checkbox. This will create the required tables for client variable storage in the database. EFK
DC>9 8;>9, 8;ID@:C ,
now consists of _hZhh^dc^Y, and H:HH>DC#JGAID@:C consists of a combination of and _hZhh^dc^Y. H:HH>DC>9 no longer uses the variable application name.
When you use session management and client management, but not Java sessions, the H:HH>DC>9 value looks like this: 8;.JH:GHT--,,T)')'-%&-
Notice how the H:HH>DC>9 is configured with a combination of the application name, 8;>9, and 8;ID@:C. You can test this yourself by using the 1X[Yjbe3 tag to dump the contents of both the client structure and the session structure.
J\i`Xc`q`e^:fc[=lj`fe:fdgfe\ekj One of the powerful features of ColdFusion 9 is the capability to serialize ColdFusion Components, allowing you to save them to files, stream them over the Internet, or more important for this chapter, share them across H:HH>DC scopes in a J2EE cluster (see Chapter 49, “Scaling with J2EE,” for more on setting up a ColdFusion cluster). ColdFusion does this by taking advantage of Java’s serialization API (see Chapter 68 for information about how you can use Java to serialize CFCs to a file).
105
106
CHAPTER
50
Managing Session State in Clusters
This capability is especially useful if you regularly put CFCs in the H:HH>DC scope in your application because it allows you to share CFCs in a session even if one of your servers in a cluster goes down. To set this up, you first need to make sure that you have J2EE sessions turned on (see “Java Sessions” earlier in this chapter). CFC serialization lets you use J2EE session replication to automatically replicate sessions across a cluster, giving you access to the CFCs in a H:HH>DC scope on any server in a cluster. This feature supports most ColdFusion variables, including structures, in a replicated H:HH>DC scope. You can also preserve and access data in a CFC in the event of session failover (if a machine in the cluster fails and other machines then have to pick up its load and state). ColdFusion structures stored within the H:HH>DC scope are available in the H:HH>DC scope, even after failure of the server. For example, if you are running multiple ColdFusion instances to balance server load, you can store useful data, including CFCs, within the session so that you can access the data across all the pages that are served in that session. Enabling CFC serialization is easy. All you have to do is set the CFC in your H:HH>DC scope like this: 1X[hZiX[XXdbedcZci28gZViZDW_ZXi¹XdbedcZciº!¹bnH]dee^c\8Vgiº3 1X[hZihZhh^dc#jhZg8Vgi2bnH]dee^c\8Vgi3
Then, from any machine, you can check a specific CFC, like this: 1X[hZiX]ZX`2hZhh^dc#jhZg8Vgi#kZg^[n96I68Vgi>93
?Xi[nXi\$9Xj\[J\jj`feDXeX^\d\ek Some hardware load-balancing devices, such as Cisco LocalDirector, offer sticky management of cookie states. The load balancer works in concert with the Web server to create session-based cookies. These cookies create a session for the user. Both the load balancer and the Web server can manipulate and read them. Some load balancers can operate in Cookie-Rewrite, Cookie-Passive, or Cookie-Insert modes. In the Cookie-Rewrite mode, the Web server creates the cookie, and the load balancer will rewrite it. Cookie-Passive mode looks for a cookie set by the Web server but will not create a cookie of its own. It attempts to learn the cookie to manage session state. If no cookie is present, CookiePassive mode will not depend on a cookie to maintain state. Cookie-Insert mode allows the load balancer to create a cookie and set it on the client. In this mode, the load balancer first looks for a cookie; if no cookie is present, this mode connects to the client and creates a cookie. Some load balancers offer other persistence modes to manage a user session, including Secure Socket Layer (SSL), preferred server, and source. These configurations maintain session-aware sessions and provide secured connections to load-balanced servers. Talk to your network or system administrators about what options are available in your hardware solution in order to determine what makes the most sense for your specific application.
Options for Managing Session State
?pYi`[Jfclk`fej Today’s Web sites are complex applications, consisting of many pages and relying on sophisticated techniques to provide content and feature-rich user interfaces. Typically you cannot use one method for managing session state for the Web site, and so the viable solution becomes some combination of the techniques discussed in this chapter. This introduces complexities beyond the focus of this chapter, but I will offer some plausible solutions. Obviously one hybrid solution involves using cookies and client or session variables in combination to manage session state. Two cookies are stored on the client to identify the user to the server. Other hybrid solutions include using cookies or session variables to identify the user and storing all session information in a centrally located database. A cookie is polled for a user identifier that is used to query the database. This is practical for an e-commerce site, which creates a unique identifier for each user and stores all shopping cart and checkout information in a database. Each time the shopping cart information is requested, the database is queried to populate the information on the page. You can also use J2EE session management on the ColdFusion application server and utilize this hZhh^dc^Y to access user information, such as username and password. Web sites can dynamically push content to users based on their preferences or characteristics, by associating a unique identifier stored in a session variable and relating this to information residing in a database. The potential uses for session state are endless, and every developer will have a preferred method for managing and using state in Web applications. Optimal session-state management in a clustered environment complicates the issue, but you can overcome these difficulties by carefully structuring and applying these techniques in designing your Web site.
107
This page intentionally left blank
:?8GKcZiEjWQlllgddi8/Q>cZiEjWQlllgddiQ^cYZm#X[b%
KXYc\,(%, ColdFusion Compiler Command Options OPTION
DESCRIPTION
REQUIRED
X[gddi
The fully qualified path to the ColdFusion root directory (such as 8/Q8daY;jh^dc. or $dei$ XdaY[jh^dc.).
Yes
Y or YZeadn
Compile templates for sourceless deployment.
Yes for Sourceless Deployment
YZeadnY^g
The fully qualified path to the directory that will contain the compiled deployable files. This cannot be the same directory as the source directory.
Yes for Sourceless Deployment
[ or [dgXZ
Force compilation.
No
\ or YZWj\
Enable debug symbols.
No
]Zae
Displays usage information and available options.
No
hgXY^g
The fully qualified path to the directory containing the Yes templates to be compiled. This directory must be under the specified lZWgddi directory. If omitted, ColdFusion will compile all ColdFusion templates in the specified lZWgddi directory.
lZW^c[
The fully qualified path to the ColdFusion L:7">C; directory.
Yes
lZWgddi
The fully qualified path to the Web server root directory (such as 8/Q8daY;jh^dc.Qlllgddi or 8//Q>cZiejWQlllgddi.
Yes
k or kZgWdhZ
Display compiler performance statistics.
No
Choosing the Right Deployment Option
With the options in Table 51.5, you can create your own compiler script using syntax similar to the following: _VkV"Xe¹X/Q8daY;jh^dc.Qgjci^bZQa^WQ_gjc#_Vg08/Q8daY;jh^dc.QlllgddiQL:7">C;Qa^WQX[bmT WddihigVe#_Vg08/Q8daY;jh^dc.QlllgddiQL:7">C;Qa^WQX[m#_Vgº"9XdaY[jh^dc#XaVhhEVi]28/$ 8daY;jh^dc.$a^W$jeYViZh!8/$8daY;jh^dc.$a^W"9XdaY[jh^dc#a^WEVi]28/$8daY;jh^dc.$a^W XdaY[jh^dc#iddah#8dbbVcYA^cZ>ckd`Zg8dbe^aZg"X[gddi8/Q8daY;jh^dc."lZW^c[8/Q 8daY;jh^dc.QlllgddiQL:7">C;"lZWgddi8/Q8daY;jh^dc.Qlllgddi"YZeadn"hgXY^g8/Q IZhi^c\QYZeadn"YZeadnY^g8/QIZhi^c\QhdjgXZ·k
This command will compile all the ColdFusion templates (CFM, CFC, and CFR files) in the 8/Q directory and save the Java bytecode versions in the8/QIZhi^c\QhdjgXZ directory. The original files in 8/QIZhi^c\QYZeadn will retain the original CFML in a human-readable format.
IZhi^c\QYZeadn
EFK
cZiEjWQlllgddi8/Q>cZiEjWQlllgddiQ^cYZm#X[m8/QIZhi^c\QhdjgXZ%@] pflkiplj`e^Xn`c[ZXi[Xj`e8/Q>cZiEjWQlllgddiQ#X[m #fecpk_\ÔijkÔc\`jZfdg`c\[%J\\k_\ÈJ\kk`e^k_\=`c\EXd\ bV\ZJeadVYZg1$]'3 1"""8]ZX`jhZg¼hVji]dg^oVi^dcidjeadVY#"""3 1XÄ[CDI>hJhZg>cGdaZ¹ejWa^h]Zgº3 1XÄcXajYZiZbeaViZ2ºad\^c[dgb#X[bº3 1V]gZ[2º^cYZm#X[bº37VX`id^cYZm1$V31X[VWdgi3 1X[ZahZ^[>h9ZÄcZY¹;DGB#jeadVYº3 1X[eVgVbcVbZ2ºkVg^VWaZh#jeadVYY^gºYZ[Vjai2º_/Qdi]ZghZgkZgQ^bV\Zhº3 1X[ign3 1"""GZhig^XijeadVYh^oZ#"""3 1XÄ[8#8DCI:CITA:C9Vhi]ZgddijhZg#KfZ_Xe^\ k_\iffklj\i#j\\k\Z_efk\bY+')+,0#:fc[=lj`fe/1?fnkf:_Xe^\k_\Iffk8[d`e`jkiXkfiLj\ieXd\#Xk]iie/$$lll# VYdWZ#Xdb$\d$`W)%')*.%
4. In the User RDS and Administrator Access section, do the following: N
To grant the user RDS permissions, check the box for Allow RDS Access. If the Separate User Name and Password Authentication type is not enabled for RDS authentication, you will receive an alert message (Figure 53.5).
=`^li\,*%, Separate User name and Password Authentication required for userbased RDS access.
N
To grant the user access to Administrator resources, check the box for Allow Administrative Access. If the Separate User Name and Password Authentication type is not enabled for Administrator authentication, you will receive an alert message (Figure 53.6).
=`^li\,*%Separate User name and Password Authentication required for user-based Administrator access.
N
Decide whether to grant Administrator console and API access, or API access only and select the radio button next to the appropriate option.
N
In the Prohibited Roles list, select the roles that you want to grant to the user account and click the left-pointing arrows button (c, and kZg^[n8a^Zci security functions.
J\Zli`kpKX^jXe[=leZk`fej As previously mentioned, ColdFusion includes tags and functions with which to implement security and access control. Table 54.1 describes the ColdFusion security tags and functions. KXYc\,+%( ColdFusion Security Tags and Functions TAG OR FUNCTION
DESCRIPTION
1XÅd\^c3
Provides a container for user authentication code. Used with the 1XÅd\^cjhZg3 tag to validate a user login against an LDAP, database, or other user repository.
1XÅd\^cjhZg3
Identifies the authenticated user to ColdFusion by specifying the user’s ID, password, and gdaZh. Requires the cVbZ, eVhhldgY, and gdaZh attributes. Specify a comma-delimited list to the gdaZh attribute. ColdFusion evaluates white space in this attribute, so be careful not to add spaces after commas.
1XÅd\dji3
Logs the current authenticated user out of ColdFusion by completely removing the user’s authenticated ID (session) and roles. When this tag is not used, ColdFusion automatically logs users out when their sessions time out.
1X[[jcXi^dc3
The gdaZh attribute restricts function execution to authenticated users in the specified roles. The hZXjgZ?HDC attribute determines whether to prepend a security prefix to JSON-formatted return values. The kZg^[n8a^Zci attribute determines whether to require remote function calls in ColdFusion Ajax applications to include an encrypted security token.
1X[ciVji]Zci^XViZ3
Authenticates a username against the Windows domain in which the ColdFusion server is running. This tag can optionally retrieve the authenticated user’s group memberships as well. This tag was added in ColdFusion MX 7.
c6cnGdaZ
Returns true if the authenticated user is a member of any role listed in the string passed to the function.
>hJhZg>cGdaZ
Returns igjZ if the authenticated user is a member of the specified roles. Use a comma-delimited list to check multiple role assignments.
>hJhZgAd\\ZY>c
Returns igjZ if the user is authenticated.
165
166
CHAPTER
54
ColdFusion Security Options
EFK< 1X[ciVji]Zci^XViZ3i\hl`i\jpflkfilek_\:fc[=lj`fej\im`Z\XjXlj\in`k_gi`m`c\^\jkfXlk_\ek`ZXk\fk_\ilj\ij`ek_\
jg\Z`Ô\[N`e[fnj[fdX`e%@kXcjfi\hl`i\jk_\:fc[=lj`fej\im\ikfilefeXN`e[fnj[fdX`en`k_e\knfibXZZ\jjkfXgi`dXip [fdX`eZfekifcc\iG;: ]fiN`e[fnjEK+[fdX`ejfiG;:\dlcXkfiN`e[fnj8Zk`m\;`i\Zkfip[fdX`ej%
8lk_\ek`ZXk`e^n`k_1XÅd\^c3 Code all of your authentication logic between 1XÅd\^c3 tags—including database username/ password lookups, Windows authentication, LDAP logins, and so forth. The 1XÅd\^c3 tag creates a container for storing user security information—the 8;ADC scope. This scope contains two variables: 8;ADC#cVbZ and 8;ADC#eVhhldgY. These two variables are populated with a user’s login ID and password when any of the following occurs: K@G
8lk_\ek`ZXk`fecf^`ZY\kn\\e1XÅd\^c3kX^jZXeXcjfY\ZXccjkf\ok\ieXcZfdgfe\ekj#Xe[efkaljk`e$c`e\:=DC% N
A form is submitted containing input fields with the special _TjhZgcVbZ and _TeVhhldgY names. For example: 1^cejiineZ2ºiZmiºcVbZ2º_TjhZgcVbZº3 1^cejiineZ2ºeVhhldgYºcVbZ2º_TeVhhldgYº3
N
An Adobe Flash Remoting \ViZlVn8dccZXi^dc object is sent containing the hZi8gZYZci^Vah method.
K@G
=fiXe\oXdgc\f]_fnkfXlk_\ek`ZXk\m`X=cXj_I\dfk`e^#j\\8[fY\K\Z_Efk\(/-/+#È?fnkfgXjjcf^`eZi\[\ek`Xcjkf XÅd\^cm`X=cXj_I\dfk`e^ÉXk]iie/$$lll#VYdWZ#Xdb$\d$icT&-+-)% N
A request contains an Authorization Header with a username and password sent via HTTP Basic authentication.
N
A request contains an Authorization Header with a hashed username and password sent via Digest or NTLM authentication. In this case, 8;ADC#cVbZ contains the username sent by the Web server, but 8;ADC#eVhhldgY is set to an empty string.
:8LK@FE
Lj\ieXd\Xe[gXjjnfi[Xi\j\ek`eZc\Xik\oklj`e^Xj`dgc\cf^`e]fid%=cXj_I\dfk`e^j\e[jk_\lj\ieXd\&gXjjnfi[fm\i k_\Y`eXip$\eZf[\[8D=8Zk`feD\jjX^\=fidXk gifkfZfc%?KKG9Xj`ZXlk_\ek`ZXk`fej\e[jk_\lj\ieXd\Xe[gXjjnfi[`eX 9Xj\-+$\eZf[\[jki`e^n`k_\XZ_i\hl\jk%:fej`[\ilj`e^JJC?KKGJ kfj\Zli\k_\lj\ieXd\Xe[gXjjnfi[n_\eXlk_\ek`$ ZXk`e^n`k_k_\j\d\k_f[j%
The 1XÅd\^c3 tag accepts three optional attributes: N
>YaZI^bZdji.
The maximum time interval for inactivity (the period between page requests) before logging out the user. The default value is 1800 seconds (30 minutes). This attribute is ignored if the ad\^cHidgV\Z attribute is set to HZhh^dc in the 1X[Veea^XVi^dc3 tag or 6eea^XVi^dc#X[X.
ColdFusion Security Framework
N
6eea^XVi^dcId`Zc.
An application-specific identifier used to restrict the 8;ADC scope to the current application. This defaults to the current application name—specified in the 1X[Veea^XVi^dc3 tag or with the I=>H#cVbZ variable in 6eea^XVi^dc#X[X —and prevents cross-application logins. ColdFusion allows you to specify the same Veea^XVi^dcId`Zc value for multiple applications.
EFK
O6I>DCT Veea^XVi^dccVbZ2_fn\m\i#:fc[=lj`feXccfnjleeXd\[Xggc`ZXk`fej]fiA)c function returns true. The hJhZg>cGdaZ function checks the provided role against the list of roles specified in 1XÅd\^cjhZg3. K@G
@]N\Yj\im\ij\Zli`kp`jlj\[`ejk\X[f]:fc[=lj`fej\Zli`kp8;ADC #hJhZg>cGdaZh]leZk`fei\hl`i\j1XÅd\^cjhZg3%
Jkfi`e^Cf^`e@e]fidXk`fe Login credentials are stored either in a cookie or in the HZhh^dc scope, as determined by the Ad\^cHidgV\Z value as either an 6eea^XVi^dc#X[X initialization variable or in the 1X[Veea^XVi^dc3 attribute. By default, 1XÅd\^c3 sets a non-persistent cookie in the user’s browser, called X[Vji]dg^oVi^dcT Veea^XVi^dcCVbZ. The cookie value is a Base64-encoded string containing the user ID, password, and application name. This in-memory cookie is not written to disk (for example, the Xdd`^Zh#imi file) and is destroyed when the browser closes. Because ColdFusion sends this cookie with every request, users must allow in-memory cookies in their browsers. If the browser disables cookies, then the effect of the 1XÅd\^cjhZg3 tag exists only for the current page request. In this scenario, ColdFusion allows you to code the 1XÅd\^cjhZg3 outside of the 1XÅd\^c3 tag in every template you want to secure, in order to persist the login information across page requests. When storing login information in the HZhh^dc scope, ColdFusion stores the Base64-encoded user ID, password, and application name in the H:HH>DC#X[Vji]dg^oVi^dc variable. ColdFusion stores this variable in its internal memory space and uses the browser’s session cookies (8;>9 and 8;ID@:C , or ?H:HH>DC>9) for user identification. This is more secure than using cookies for login
167
168
CHAPTER
54
ColdFusion Security Options
storage because ColdFusion does not pass H:HH>DC#X[Vji]dg^oVi^dc with every page request. The user’s login and session share the same timeout value—and ColdFusion ignores the >YaZI^bZdji 1XÅd\^c3 attribute. EFK
DC#X[Vji]dg^oV" i^dccf^`emXi`XYc\`jXmX`cXYc\kfXccd\dY\ij`eXj\im\iZcljk\i%
9\jkGiXZk`Z\1:fc[=lj`feJ\jj`fejXe[8;ADC Session-scoped variables are held in ColdFusion memory space. Storing the 8;ADC authorization variable (H:HH>DC#X[Vji]Zci^XViZ) in the HZhh^dc scope (Ad\^cHidgV\Z2HZhh^dc) will persist the value for the duration of the user’s session. If the user closes the browser without logging out with 8;AD9 and 8;ID@:C or ?H:HH>DC>9) as the authenticated user, that user can impersonate the previously authenticated user. ColdFusion identifies browser sessions by cookies and URL parameters. A ColdFusion Session ID comprises the 8;>9, 8;ID@:C, and Application name (Veea^XVi^dcCVbZT8;>9T8;ID@:C). When J2EE Sessions are enabled, the Session ID is the ?H:HH>DC>9 value. A ColdFusion session can be impersonated by passing existing Session ID values on the URL or in cookies. The following are best-practice steps to prevent session impersonation: N
Use the kZg^[n8a^Zci function and 6eea^XVi^dc#X[X$1X[Veea^XVi^dc3 attribute to force ColdFusion to require the encrypted security token for ColdFusion Ajax client requests.
N
Enable J2EE session management and use ?H:HH>DC>9: N
?H:HH>DC>9
is a randomly generated, alphanumeric string created as a non-persistent
cookie. N
N
Use DC#X[Vji]Zci^XViZ).
For ColdFusion session management: N
Use a UUID for 8;ID@:C. Enable UUID for 8;ID@:C in the ColdFusion Administrator Settings page.
ColdFusion Security Framework
N
Ensure CFID and CFTOKEN are created as non-persistent values. See Adobe TechNote 17915 at ]iie/$$lll#VYdWZ#Xdb$\d$icT&,.&*.
N
Do not allow Session variables to pass on the URL. These values are not browser specific like cookies.
N
When logging out the user, ensure that 1XÅd\dji3 is called as well as HigjXi8aZVgHZhh^dc. HigjXi8aZVgHZhh^dc clears all session variables except the H:HH>DC>9 and H:HH>DC#X[Vji]Zci^XViZ values.
N
Use the DcHZhh^dcHiVgi method in the 6eea^XVi^dc#X[X to clear any existing H:HH>DC>9 values (from URL or cookie).
N
Call 1XÅd\dji3 in the DcHZhh^dc:cY method to ensure the logged-in user is logged out when the session ends.
N
When creating user sessions inspect 8#=IIETG:;:G:G to ensure the request is coming from within the application.
Cf^^`e^Flk There are several ways to log out users and remove their login information from ColdFusion. The primary method is to use the 1XÅd\dji3 tag. ColdFusion MX did a poor job of destroying session information after a user logged out. Table 54.2 lists the circumstances in which ColdFusion logs out the current user and destroys the 1XÅd\^cjhZg3 authentication credentials. KXYc\,+%) ColdFusion User Logout DESCRIPTION
Ad\^cHidgV\Z28dd`^Z Ad\^cHidgV\Z2HZhh^dc
Application fires 1XÅd\dji3
x
x
The1XÅd\^c3 >YaZI^bZdji value is reached
x
N/A
The user closes all browser windows
x
N/A
The ColdFusion session ends
N/A
x
:8LK@FE 1XÅd\dji3[f\jefkZc\Xik_\cf^`e`e]fidXk`fe`]pflXlk_\ek`ZXk\lj\ijm`XN\Yj\im\ij\Zli`kpfik_\?KKG8lk_fi`qXk`fe
_\X[\i%K_\j\j\Zli`kpgXiX[`^djZfek`el\kfj\e[Xlk_\ek`ZXk`fe`e]fidXk`fekf:fc[=lj`felek`cXccYifnj\in`e[fnjXi\ Zcfj\[%K_\i\]fi\#lek`cXccYifnj\in`e[fnjXi\Zcfj\[#k_\8;ADCjZfg\dXpg\ij`jkY\pfe[lj\icf^flk#gifm`[`e^Xn`e$ [fnf]fggfikle`kp]fiXefk_\ilj\ikf`dg\ijfeXk\k_\Ôijklj\i%
Executing 1XÅd\dji3 when using Ad\^cHidgV\Z2HZhh^dc removes the H:HH>DC#X[Vji]dg^oVi^dc variable from the HZhh^dc scope, but does not end the current user’s session. Therefore, if you want to log the user out and completely clear his or her session, you must code logic that calls 1XÅd\dji3 and HigjXi8aZVgHZhh^dc: 1XÄ[>h9ZÄcZY»JGA#Ad\dji¼VcYJGA#Ad\dji3 1XÅd\dji3 1X[hZiHigjXi8aZVgHZhh^dc3 1$XÄ[3
169
170
CHAPTER
54
ColdFusion Security Options
K@G
:Xcc`e^HigjXi8aZVgHZhh^dcn`ccefk^\e\iXk\Xe\nj\jj`fe`[Ylk`kn`ccZfdgc\k\cp\dgkpk_\Jh9ZÄcZY¹G:FJ:HI#WVYad\^cº31heVchinaZ2ºXdadg/gZYº3Ndjgad\^c^c[dgbVi^dclVh ^ckVa^Y1$heVc31$XÄ[3 1"""JhZX[[dgbidegdk^YZXa^Zci"h^YZ_VkVhXg^eikVa^YVi^dcdci]ZjhZgcVbZ [dgbÄZaY#"""3
171
172
CHAPTER
54
ColdFusion Security Options
C`jk`e^,+%) (continued) 1X[[dgbVXi^dc2º^cYZm#X[bºbZi]dY2ºedhiº3 1iVWaZWdgYZg2º%º3 1ig3 1iY3JhZgCVbZ/1$iY3 1iY31XÄcejiineZ2ºiZmiºcVbZ2º_TjhZgcVbZºbZhhV\Z2ºNdjbjhiZciZgVjhZgcVbZº gZfj^gZY2ºnZhº31$iY3 1$ig3 1ig3 1iY3EVhhldgY/1$iY3 1iY31XÄcejiineZ2ºeVhhldgYºcVbZ2º_TeVhhldgYºbZhhV\Z2ºNdjbjhiZciZgV eVhhldgYºgZfj^gZY2ºnZhº31$iY3 1$ig3 1ig3 1iY3cWhe01$iY3 1iY31^cejiineZ2ºgZhZiº3q1^cejiineZ2ºhjWb^iºcVbZ2ºad\dcºkVajZ2ºAd\^cº31$iY3 1$ig3 1$iVWaZ3 1$X[[dgb3 1$WdYn3 1$]iba3
K@G
K_\_TjhZgcVbZXe[_TeVhhldgYmXcl\jXi\jlYd`kk\[XjZc\Xik\ok%=fi^i\Xk\ij\Zli`kp#Zfej`[\ilj`e^JJCkfgi\m\ek \Xm\j[ifgg`e^XkkXZbj%
The ad\^c;dgb#X[b template contains the actual form that submits the username and password. These are processed by the 6eea^XVi^dc#X[b when the form is submitted. The code in 6eea^XVi^dc #X[b will allow processing to continue with ^cYZm#X[b if authentication is successful; otherwise, the login form will redisplay. C`jk`e^,+%* ^cYZm#X[b —Securing a Template with hJhZg>cGdaZ 1X[h^aZci3 1""" ;^aZCVbZ/^cYZm#X[b 9ZhXg^ei^dc/>cYZmeV\ZhZXjgZYWn1XÅd\^c3^ci]Z6eea^XVi^dc#X[b#I]^h eV\ZVahdh]dlh]dlidjhZi]Z8daY;jh^dchZXjg^in[jcXi^dch/ hJhZg>cGdaZ# 6hhjbei^dch/CdcZ 6ji]dgcVbZVcYZ"bV^a/HVg\ZhVg\Z5hVg\ZlVn#Xdb 9ViZ8gZViZY/?jan')!'%%' 8]Vc\ZAd\/JeYViZY;ZWgjVgn'%!'%%* """3 1$X[h^aZci3 1YdXineZ]ibaejWa^X¹"$$l(X$$YiY]iba)#%&igVch^i^dcVa$$Zcº3 1]iba3 1WdYn3 1"""JhZi]ZhJhZg>cGdaZ[jcXi^dcidVYYXdcY^i^dcVaad\^XWVhZYdci]Z jhZg¼h\gdjebZbWZgh]^egdaZ#"""3 1XÄ[>hJhZg>cGdaZ¹VYb^chº3 1e37VhZYdcndjgad\^c>9!ndjVgZeZgb^iiZYidVXXZhhi]^hhZXi^dcd[i]Z h^iZ#1Wg$3
ColdFusion Login Wizard Extension
C`jk`e^,+%* (continued) EaZVhZegdXZZYidi]Z1V]gZ[2º^cYZm#X[bºi^iaZ2ºI]^ha^c`^h[dgYZbdchigVi^dc ejgedhZhdcanº36Yb^c^higVidg¼hhZXi^dc1$V3#1$e3 1"""9^heaVni]Zad\djia^c`#"""3 1e31V]gZ[2º^cYZm#X[b4ad\dji2nZhº3Ad\Dji1$dc31$e3 1$XÄ[3 1$WdYn3 1$]iba3
:fc[=lj`feCf^`eN`qXi[ and logs out the current user. It also calls the method if Browser Dialog Box was selected as the challenge method in the wizard. The call to XadhZ7gdlhZg prevents the browser from continuing to send old login information after the call to 1XÅd\dji3. ad\dji
XadhZ7gdlhZg
N
This method uses JavaScript to prompt the user to close the browser and/or closes the browser to complete the logout process.
XadhZ7gdlhZg:
177
178
CHAPTER
N
54
ColdFusion Security Options
bbTl^oVgYTad\^c#X[b#
The login form presented to the user if ColdFusion login was
chosen in the wizard. K@G 6eea^XVi^dc#X[Xfm\ii`[\jXep6eea^XVi^dc#X[bk\dgcXk\j`ek_\jXd\[`i\ZkfipgXk_%:fej`[\idfm`e^pfli Xggc`ZXk`fecf^`Z`e6eea^XVi^dc#X[bkfk_\Xggc`ZXk`fe\m\ek_Xe[c\ij`e6eea^XVi^dc#X[X%J\\k_\ÈD`^iXk`e^]ifd 6eea^XVi^dc#X[bkf6eea^XVi^dc#X[XÉj\Zk`fef]k_\Z_Xgk\iÈ;\j`^e`e^Xe[Fgk`d`q`e^X:fc[=lj`fe8ggc`ZXk`feÉ `ek_\:fc[=lj`fe/;\m\cfg\iËj>l`[\_\cgdXelXcXk]iie/$$a^kZYdXh#VYdWZ#Xdb$XdaY[jh^dc$-$]ibaYdXh$ Vee;gVbZldg`T&*#]iba&&.&)*)%
The code generated by the wizard can be used as is for the most part; however, it has some shortcomings that you should customize before putting it into production: N
The 6eea^XVi^dc#X[X contains no initialization variables, including application name, or the like. You should code these variables to strengthen your security paradigm.
Ad\^cHidgV\Z, HZhh^dcBVcV\ZbZci, HZhh^dcI^bZdji, HZi8a^Zci8dd`^Zh,
N
Consider changing the h^beaZ6ji] authentication method to perform a database query using the submitted username and password instead of a simple string comparison. Use the =Vh] function to strengthen the security of passwords in the database. See Chapter 52 for more information on the ColdFusion 9 =Vh] function.
N
The authentication methods contain simplified code and may not work without modification. For example, the LDAP code queries for an attribute named ¹gdaZhº, which is probably not valid for most LDAP servers.
N
The authentication methods only return Boolean values in ColdFusion structures that indicate whether authentication failed. Modify the code to populate the structure with the authenticated user’s roles, as well.
N
All authenticated users are granted a single role: user. Modify this hard-coded 1XÅd\^" cjhZg3 value in the eZg[dgbAd\^c method to dynamically accept roles returned from the authentication methods.
N
The wizard allows you to specify a Browser dialog box, but it does not allow you to specify the authentication realm. Modify the default Basic Realm values in the 1X[]ZVYZg3 tag in the eZg[dgbAd\^c method.
N
The wizard creates a default error message for login failures, but it does not create code for handling any exceptions, such as domain controller access failures or LDAP failure codes.
K@G
:_ffj`e^k_\i`^_kcf^`eZ_Xcc\e^\`j`dgfikXek%J\c\Zk9ifnj\i;`Xcf^9fo`]pflXi\`ek\^iXk`e^n`k_N\Yj\im\iXlk_\ek`ZXk`fe# fiZ_fj\EK;fdX`eXjk_\Xlk_\ek`ZXk`fekpg\%Lj\X:fc[=lj`fecf^`egX^\]fi[XkXYXj\Xe[C;8Gcf^`ej#Y\ZXlj\X[XkXYXj\ Xe[C;8GnfeËkY\XYc\kfmXc`[Xk\k_\9Xj`ZI\Xcdf]k_\NNN8lk_\ek`ZXk`fe_\X[\igXjj\[Ypk_\9ifnj\i[`Xcf^Yfo%
ColdFusion Login Wizard Extension
:fc[=lj`feCf^`eN`qXi[H#cVbZ variable, to set the application name. The bbTl^oVgYT^cXajYZ#X[b in Listing 54.6 records the parameters entered into the wizard fields and passes them to the bbT l^oVgYT Vji]Zci^XViZ#X[X. The h^beaZVji] and aYVeVji] methods have been removed from the bbT l^oVgYTVji]Zci^XViZ#X[X in Listing 54.7. The ciVji] method has been modified to return the authentication structure returned from the 1X[ciVji]Zci^XViZ3, which is used to log in the user. Table 54.3 lists the 1X[ciVji]Zci^XViZ3 attributes; Table 54.4 lists the fields in the returned structure. K@G
@]pflËi\]Xd`c`Xin`k_g\i]fid`e^Xlk_\ek`ZXk`feXe[Xlk_fi`qXk`fe`epfli6eea^XVi^dc#X[b#dfm\k_\1XÅd\^c3Zfe$ kX`e\i`ekfk_\DcGZfjZhiHiVgid\k_f[f]k_\6eea^XVi^dc#X[X%
KXYc\,+%* 1X[ciVji]Zci^XViZ3 Attributes ATTRIBUTE
DESCRIPTION
REQUIRED
jhZgcVbZ
A username to authenticate against the specified domain.
Yes
eVhhldgY
The password for the specified username.
Yes
YdbV^c
Windows domain to authenticate against. ColdFusion must be Yes running on a server within the specified domain.
gZhjai
Variable name for the return structure. Default value is X[Vji]Zci^XViZ.
No
a^hiO6G98D9:/:C9"""3
C`jk`e^,+%. bbTl^oVgYTVji]Zci^XViZ#X[X —ColdFusion Wizard’s Authentication File 1""" ;^aZcVbZ/bbTl^oVgYTVji]Zci^XViZ#X[X 9ZhXg^ei^dc/BdY^ÄZY8daY;jh^dcAd\^cL^oVgYiZbeaViZi]VieZg[dgbhjhZg Vji]Zci^XVi^dcVcYad\^c# 6hhjbei^dch/I]^hiZbeaViZdcaneZg[dgbhL^cYdlhVji]Zci^XVi^dc""Vaadi]Zg Vji]Zci^XVi^dcbZi]dYhVgZgZbdkZY# 6ji]dgcVbZVcYZ"bV^a/HVg\ZhVg\Z5hVg\ZlVn#Xdb 9ViZ8gZViZY/;ZWgjVgn''!'%%* """3
181
182
CHAPTER
54
ColdFusion Security Options
C`jk`e^,+%. (continued) 1X[XdbedcZci3 1""""$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"""3 1""""CI9dbV^c6ji]Zci^XVi^dc"""3 1""""$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"""3 1X[[jcXi^dccVbZ2ºciVji]ºVXXZhh2ºeg^kViZºdjieji2º[VahZºgZijgcineZ2ºhigjXiº ]^ci2º6ji]Zci^XViZV\V^chiVCIYdbV^cº3 1X[Vg\jbZcicVbZ2ºcjhZgcVbZºgZfj^gZY2ºigjZº]^ci2ºI]ZjhZgcVbZº3 1X[Vg\jbZcicVbZ2ºceVhhldgYºgZfj^gZY2ºigjZº]^ci2ºI]ZeVhhldgYº3 1X[Vg\jbZcicVbZ2ºcYdbV^cºgZfj^gZY2ºigjZº]^ci2ºI]ZYdbV^cidVji]Zci^XViZ V\V^chiº3 1"""BdY^[ni]Z1X[ciVji]Zci^XViZ3WnhZii^c\a^hi\gdjeh2nZh"""3 1X[ciVji]Zci^XViZ jhZgcVbZ2ºVg\jbZcih#cjhZgcVbZº eVhhldgY2ºVg\jbZcih#ceVhhldgYº YdbV^c2ºVg\jbZcih#cYdbV^cº gZhjai2ºVji]Zci^XViZYº a^hi\gdjeh2ºnZhº3 1X[gZijgcVji]Zci^XViZY3 1$X[[jcXi^dc3 1""""$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"""3 1"""I]^hbZi]dYeZg[dgbhi]Z1XÅd\^c3XVaaVcY^cijgc"""3 1"""XVaahi]ZVXijVaVji]Zci^XVi^dcbZi]dY"""3 1""""$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"""3 1X[[jcXi^dccVbZ2ºeZg[dgbad\^cºVXXZhh2ºejWa^Xºdjieji2ºigjZº]^ci2ºAd\VjhZg^c jh^c\Z^i]ZgCIVji]Zci^XVi^dc#º3 1X[Vg\jbZcicVbZ2ºVg\hºineZ2ºhigjXiºgZfj^gZY2ºigjZº]^ci2ºI]ZhZVgZi]Z eVgVbZiZghhZijeWni]ZAd\^cL^oVgYº3 1XÅd\^c3 1XÄ[CDI>h9ZÄcZY¹XÅd\^cº3 1XÄcXajYZiZbeaViZ2ºVg\h#ad\^c[dgbº31X[VWdgi3 1X[ZahZ3 1X[ign3 1XÄckd`ZbZi]dY2ºciVji]º gZijgckVg^VWaZ2ºgZhjaiº cjhZgcVbZ2ºXÅd\^c#cVbZº ceVhhldgY2ºXÅd\^c#eVhhldgYº cYdbV^c2ºVg\h#YdbV^cº3 1X[XViX]3 1X[hZiZggdgBZhhV\Z2¹Ndjgad\^c^c[dgbVi^dc^hcdikVa^Y#1Wg3EaZVhZ IgnV\V^cº3 1XÄcXajYZiZbeaViZ2ºVg\h#ad\^c[dgbº31X[VWdgi3 1$X[XViX]3 1$X[ign3 1$XÄ[3 1"""kVa^YViZ^[i]ZjhZg^hVji]Zci^XViZY"""3 1XÄ[gZhjai#Vji]Zf¹N:Hº3 1"""^[Vji]Zci^XViZY"""3 1XÅd\^cjhZgcVbZ2ºXÅd\^c#cVbZºeVhhldgY2ºXÅd\^c#eVhhldgYº gdaZh2ºgZhjai#\gdjehº3 1X[ZahZ3 1"""^[cdiVji]Zci^XViZY!gZijgcidad\^c[dgbl^i]VcZggdgbZhhV\Z"""3 1X[hZiZggdgBZhhV\Z2¹Ndjgad\^c^c[dgbVi^dc^hcdikVa^Y#1Wg3EaZVhZIgn V\V^cº3 1XÄcXajYZiZbeaViZ2ºVg\h#ad\^c[dgbº31X[VWdgi3 1$XÄ[3
ColdFusion Login Wizard Extension
C`jk`e^,+%. (continued) 1$XÅd\^c3 1$X[[jcXi^dc3 1""""$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"""3 1"""Ad\dji"""3 1""""$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"""3 1X[[jcXi^dccVbZ2ºad\djiºVXXZhh2ºgZbdiZºdjieji2ºigjZº]^ci2ºAd\i]ZjhZgdji#º3 1X[Vg\jbZcicVbZ2ºad\^cineZºineZ2ºhig^c\ºgZfj^gZY2ºnZhº]^ci2ºI]Zad\^cineZ jhZYidad\^c#º3 1XÄ[^h9ZÄcZY¹[dgb#ad\djiº3 1XÅd\dji3 1XÄ[Vg\jbZcih#ad\^cineZZf¹X]VaaZc\Zº3 1X[hZi[dd2XadhZ7gdlhZg3 1X[ZahZ3 1"""gZeaVXZi]^hJGAidVeV\Zad\\ZYdjijhZghh]djaYhZZ"""3 1XÅdXVi^dcjga2º]iie/$$lll#6YdWZ#Xdbº3 1$XÄ[3 1$XÄ[3 1$X[[jcXi^dc3 1""""$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"""3 1"""8adhZ7gdlhZg"""3 1"""IdZchjgZi]Z]ZVYZgVji]Zci^XVi^dc^c[dgbVi^dc"""3 1"""]VhWZZci]djgdj\]anÅjh]ZYi]ZWgdlhZgh]djaYWZXadhZY"""3 1""""$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"""3 1X[[jcXi^dccVbZ2ºXadhZ7gdlhZgºVXXZhh2ºejWa^Xºdjieji2ºigjZº]^ci2º8adhZi]Z WgdlhZgidXaZVgi]Z]ZVYZg^c[dgbVi^dc#º3 1hXg^eiaVc\jV\Z2º_VkVhXg^eiº3 ^[cVk^\Vidg#VeeCVbZ22¹B^Xgdhd[i>ciZgcZi:meadgZgºp VaZgi¹I]ZWgdlhZgl^aacdlXadhZidXdbeaZiZi]Zad\dji#º0 l^cYdl#XadhZ0 r ^[cVk^\Vidg#VeeCVbZ22¹CZihXVeZºp VaZgi¹IdXdbeaZiZi]Zad\djindjbjhiXadhZi]^hWgdlhZg#º0 r 1$hXg^ei3 1$X[[jcXi^dc3 1$X[XdbedcZci3
183
This page intentionally left blank
:?8GKC;$X[jh^dc$a^W$XdaY[jh^dc#eda^Xnº "9_VkV#hZXjg^in#Vji]#eda^Xn2ºX[Tgddi$L:7">C;$X[jh^dc$a^W$cZdT_VVh#eda^Xnº
2. Expand the Security section in the left navigation pane (if it’s not already expanded). 3. Click the Sandbox Security link. 4. Check the box next to Enable ColdFusion Security in the window on the right. Click Submit. The page should refresh and display the success message (Figure 55.4). 5. Restart ColdFusion.
191
192
CHAPTER
55
Creating Server Sandboxes
=`^li\,,%+ You must manually enable sandbox security using the Sandbox Security page and restart ColdFusion.
K@G
@]k_\c`eb`ek_\J\Zli`kpj\Zk`fef]k_\8[d`e`jkiXkfieXm`^Xk`fegXe\jXpjÈI\jfliZ\J\Zli`kp#Épfl_Xm\k_\:fc[=lj`feJkXe$ [Xi[\[`k`feXe[n`ccefkY\XYc\kfZfeÔ^li\X[[`k`feXcjXe[Yfo\j%
Notice that after you enable sandbox security, ColdFusion automatically creates the two sandboxes (shown in Figure 55.4): N
ColdFusion CFIDE system directory
N
ColdFusion WEB-INF system directory
You can edit these two internal, system-level sandboxes, but you cannot delete them. EFK
E6YYgZhhZh1$i]31$ig3 1X[djieji31XÅddea^hi2ºG:FJ:HI#bn6Yb^cDW_#\Zi>EA^hiº^cYZm2º^º3 1ig31iY3^1$iY31$ig3 1$XÅdde31$X[djieji3 1$iVWaZ3
241
242
CHAPTER
57
Using the Administrator API
J\Zli`kp@dgc`ZXk`fej]fik_\8[d`e8G@ Before using the ColdFusion Admin API, certain security implications need consideration. Administrators must understand the potential for allowing unfettered access to the ColdFusion Administrator. ColdFusion secures the ColdFusion Administrator with a single password, which administrators should not provide to users. Administrators must also enable access to the Admin API code directory: $8;>9:$6Yb^c6E>. This directory is installed by default, and the API modules are hardcoded to look for this path.
:fc[=lj`feHZgk^XZ;VXidgn Soon after ColdFusion MX was released, developers learned how to access the ColdFusion HZgk^XZ;VXidgn object, by using 8gZViZDW_ZXi and 1X[dW_ZXi3 calls to XdaY[jh^dc#hZgkZg# HZgk^XZ;VXidgn. This Java object gave developers complete access to all ColdFusion server objects, including the Data Source, Licensing, Runtime, and Security Services. It also allowed developers to bypass the ColdFusion Administrator to programmatically configure data sources, debugging, and so on. Hackers could also use it to disable the admin and RDS passwords and gain complete control over the server. In response, Macromedia expanded the sandbox security restrictions in ColdFusion MX 7 for 8gZViZDW_ZXi, allowing administrators to disable access to Java objects. This allowed administrators to use sandbox security to disable HZgk^XZ;VXidgn access. Adobe improved HZgk^XZ;VXidgn security in ColdFusion 8 by providing the Disable Access to Internal ColdFusion Java Components ColdFusion Administrator option. This option prevents unauthorized access to the internal ColdFusion objects while permitting developer access to other legitimate Java objects. Using this option with sandbox security and user-based administrator access, administrators have control over Admin API access. EFK
DChXdeZ#"""3 1X[hZiHigjXi9ZaZiZH:HH>DC!bn6Yb^cDW_3 1$XÄ[3 1$XÅdX`3 1"""Ad\i]ZjhZgdjid[8daY;jh^dc#"""3 1XÅd\dji3 1$XÄ[3 1"""8;ADChigjXijgZ[dgVji]Zci^XVi^dcXdYZ#"""3 1XÅd\^c3 1X[hZiG:FJ:HI#ad\\ZY^c2[VahZ3 1XÄ[>h9ZÄcZY¹XÅd\^cº3 1"""6ji]Zci^XViZVcYad\^cjhZgid8daY;jh^dcl^i]Veegdeg^ViZgdaZh# """3 1XÄ[cdi8dbeVgZCd8VhZ»VYb^c¼!Ig^b8;ADC#cVbZVcY cdi8dbeVgZCd8VhZIg^b8;ADC#eVhhldgY!¹eVhhldgYº3 1XÅd\^cjhZgcVbZ2º8;ADC#cVbZºeVhhldgY2º8;ADC#eVhhldgYº gdaZh2ºVYb^c!ejWa^h]Zgº3 1X[hZiG:FJ:HI#ad\\ZY^c2¹igjZº3 1X[ZahZ3 1X[hZiG:FJ:HI#WVYad\^c2¹igjZº3 1X[hZiG:FJ:HI#ad\\ZY^c2¹[VahZº3 1""">[i]Zad\^c[V^ah!gZijgcidi]Zad\^c[dgb#"""3 1XÄcXajYZiZbeaViZ2ºad\^c[dgb#X[bº31X[VWdgi3 1$XÄ[3
245
246
CHAPTER
57
Using the Administrator API
1X[ZahZ3 1XÄcXajYZiZbeaViZ2ºad\^c[dgb#X[bº31X[VWdgi3 1$XÄ[3 1$XÅd\^c3 1XÄ[AZcIg^b#"""3 1X[hZiH:HH>DC#bn6Yb^cDW_2XgZViZDW_ZXi¹XdbedcZciº!¹dlh#X]VeiZg*,# [VXVYZº#ad\^c67A:H#VYb^cEVhhlY;^aZ!¹6Yb^cTEVhhº!¹eVhhldgYº3 1$XÄ[3 1"""8gZViZVG:FJ:HIhXdeZed^ciZg[dgjhZ^cdi]ZgiZbeaViZhdc hjWhZfjZcigZfjZhih#"""3 1X[hZiG:FJ:HI#bn6Yb^cDW_2H:HH>DC#bn6Yb^cDW_3 1$XÅdX`3 1X[djieji3 1"""6YYAd\dji7jiidcVideZkZgneV\Z#"""3 1X[[dgbcVbZ2º:m^iºVXi^dc2º^cYZm#X[bº3 1XÄcejiineZ2ºhjWb^iºcVbZ2ºAd\djiºkVajZ2ºAd\djiº3 1$X[[dgb3 1$X[djieji3 1$XÄ[3 1$X[[jcXi^dc3 1X[[jcXi^dccVbZ2ºdcHZhh^dc:cYºgZijgcineZ2ºkd^Yº3 1X[Vg\jbZcicVbZ2ºHZhh^dcHXdeZºgZfj^gZY2ºigjZº3 1X[Vg\jbZcicVbZ2º6eea^XVi^dcHXdeZºgZfj^gZY2º[VahZº3 1XÅdX`hXdeZ2ºhZhh^dcºi^bZdji2º(%ºi]gdldci^bZdji2ºnZhº3 1XÄ[>h9ZÄcZY¹H:HH>DC#bn6Yb^cDW_º3 1""":chjgZi]ZjhZg^had\\ZYdjid[i]Z6Yb^c6E>#"""3 1X[hZiH:HH>DC#bn6Yb^cDW_#ad\dji3 1""":chjgZi]Z[VXVYZdW_ZXi^hXaZVgZY[gdbi]ZH:HH>DChXdeZ#"""3 1X[hZiHigjXi9ZaZiZH:HH>DC!bn6Yb^cDW_3 1$XÄ[3 1$XÅdX`3 1""":chjgZi]ZjhZg^had\\ZYdjid[8daY;jh^dc#"""3 1XÅd\dji3 1$X[[jcXi^dc3 1$X[XdbedcZci3
Listing 57.4 shows the CF Admin password hard-coded in the 6eea^XVi^dc#X[X (see the K6G>67A:H#VYb^cEVhhlY variable). This is necessary for the façade to work. The code uses K6G>67A:H# VYb^cEVhhlY to authenticate to the [VXVYZ#X[X. Revisit the [VXVYZ#X[X code in Listing 57.1. We can secure the method calls using the 1X[[jcXi^dc3gdaZh attribute. Specifying gdaZh2ºVYb^cº will require users to authenticate with the role of VYb^c in order to run the façade methods. (This sample code provided for this chapter is already secured with gdaZh2ºVYb^cº.)
Admin API Best Practices
K@G
K_\[VXVYZ#X[Xd\k_f[j`eC`jk`e^,.%(Xi\XcjfXmX`cXYc\XjN\Yj\im`Z\jYpm`ikl\f]VXXZhh2ºgZbdiZº`ek_\ 1X[[jcXi^dc3ZXccj%N_\egdaZh2ºVYb^cº`jjg\Z`Ô\[i\dfk\Zc`\ekjXi\Xcjfi\hl`i\[kfXlk_\ek`ZXk\kf:fc[=lj`feXj Xlj\in`k_k_\VYb^cifc\`efi[\ikflj\k_\N\Yj\im`Z\%
The 6eea^XVi^dc#X[X ensures only authorized ColdFusion users can access the [VXVYZ#X[X. It forces users to a login form where they must enter authentication criteria. Upon successful authentication, 1XÅd\^cjhZg3 logs the user into the ColdFusion security paradigm with the role of VYb^c. If DC scope and authenticated to the Admin API: 1XÄ[CDI>h9ZÄcZY¹H:HH>DC#bn6Yb^cDW_º3 1X[hZiH:HH>DC#bn6Yb^cDW_2XgZViZDW_ZXi¹XdbedcZciº!¹dlh#X]VeiZg*,#[VXVYZº# ad\^cK6G>67A:H#VYb^cEVhhlY3 1$XÄ[3
This H:HH>DC scope object ensures authenticated access for every request during the user’s session. Next, provide a handle to the H:HH>DC object in the G:FJ:HI scope to eliminate any locking concerns: 1X[hZiG:FJ:HI#bn6Yb^cDW_2H:HH>DC#bn6Yb^cDW_3
Finally, the 6eea^XVi^dc#X[X includes logout code to exit the Admin API, logout of ColdFusion, and destroying of the H:HH>DC scope façade object: 1XÅdX`hXdeZ2ºhZhh^dcºi^bZdji2º(%ºi]gdldci^bZdji2ºnZhº3 1XÄ[>h9ZÄcZY¹H:HH>DC#bn6Yb^cDW_º3 1""":chjgZi]ZjhZg^had\\ZYdjid[i]Z6Yb^c6E>#"""3 1X[hZiH:HH>DC#bn6Yb^cDW_#ad\dji3 1""":chjgZi]Z[VXVYZdW_ZXi^hXaZVgZY[gdbi]ZH:HH>DChXdeZ #"""3 1X[hZiHigjXi9ZaZiZH:HH>DC!bn6Yb^cDW_3 1$XÄ[3 1$XÅdX`3 1""":chjgZi]ZjhZg^had\\ZYdjid[8daY;jh^dc#"""3 1XÅd\dji3
EFK
86I>DC. Even though it can maintain a connection across multiple pages, it is recommended that you keep it open only for the duration of your requests. Managing the number of unique connections to the FTP server is critical because most FTP servers allow a set number of concurrent connections at any one time. Having a persistent connection to the FTP server effectively ties up one of the connections to the server Depending on the FTP server you are connecting to, making changes to cached connection settings, such as changing gZign8djci or i^bZdji, will require shutting down and reestablishing the connection.
=`c\Xe[;`i\ZkfipFg\iXk`fejn`k_1X[[ie3 After you establish an FTP connection, you can perform various file and directory operations to send files to the server or receive files and directory listings from the server. Table 58.5 shows the attributes for file and directory operations. KXYc\,/%, 1X[[ie3 File and Directory Operation Attributes ATTRIBUTE
DESCRIPTION
VXi^dc
Required if the connection is not already cached using the XdccZXi^dc attribute. Determines the FTP operation to perform. It can be one of the following: 8]Vc\Z9^g, 8gZViZ9^g, GZbdkZ9^g, A^hi9^g, [:m^hih
Optional. N:H or CD. Defaults to N:H. Specifies whether a i^hi]ZdcaniV\^cMBAi]ViYdZhcdi ]VkZVcZcYiV\# ""3 1lhYa/YZÄc^i^dch3 1"" 6hi]ZGddiZaZbZcid[VLH9AÄaZ!i]ZdeZc^c\1lhYa/YZÄc^i^dch3iV\ YZÄcZhVaaVeea^XVWaZMBAcVbZheVXZhidVkd^YcVb^c\XdcÅ^Xih WZilZZc^YZci^XVaancVbZYMBAiV\h ""3 1lhYa/ineZh3 1"" I]Z1lhYa/ineZh3iV\YZÄcZheaVi[dgb"cZjigVaYViVineZ YZÄc^i^dch[gdbi]ZMBAHX]ZbVheZX^ÄXVi^dc#I]ZhZVgZi]Z YViVineZhi]ViVgZjhZY[dgbZhhV\Zh# ""3 1$lhYa/ineZh3 1lhYa/bZhhV\Z3 1""8dYZYZhXg^W^c\LH9A¹bZhhV\Zº I]Z1lhYa/bZhhV\Z3iV\YZÄcZhi]ZXdbbjc^XVi^dcYViVZaZbZcih# :VX]bZhhV\ZXdch^hihd[dcZdgbdgZad\^XVa1lhYa/eVgi3iV\h# 1lhYa/eVgi3iV\hXdciV^ccVbZVcYLH9AYViZineZ^c[dgbVi^dcVcY VgZh^b^aVgidi]ZeVgVbZiZghd[VbZi]dYXVaa^c?VkVdg [jcXi^dcXVaa^c8 dg8daY;jh^dc# ""3 1$lhYa/bZhhV\Z3 1lhYa/edgiIneZ3 1""8dYZYZhXg^W^c\LH9A¹edgiº I]Z1lhYa/edgiIneZ3iV\YZÄcZhdeZgVi^dch[jcXi^dchi]ViXVc WZXVaaZYl^i]^cVLZWHZgk^XZ!VcYi]ZbZhhV\Zh^cejidjieji eVgVbZiZghi]ViVgZ^ckdakZY#NdjXVci]^c`d[VedgiIneZVh WZ^c\hdbZl]Vih^b^aVgidVXaVhh^c?VkVdg8 #>c[VXi!V edgiIneZ^hVabdhiZmVXiana^`ZV8;8^ci]Vi^iXdciV^chbZi]dYh WjiXVc¼iWZ^chiVci^ViZYVcYYdZhc¼i]VkZbZbWZgkVg^VWaZh#6c deZgVi^dc^hZmigZbZanh^b^aVgidV[jcXi^dc^cVhigjXijgZY egd\gVbb^c\aVc\jV\ZhjX]Vh8dg8daY;jh^dc# ""3 1$lhYa/edgiIneZ3 1lhYa/W^cY^c\3 1"" 8dYZl^i]^ci]ZdeZc^c\VcYXadh^c\1lhYa/W^cY^c\3iV\ YZÄcZhi]ZLH9A¹W^cY^c\ºd[YViVineZh[dgVaa^ceji VcYdjiejieVgVbZiZghVhlZaaVhidi]Z^gZcXdY^c\hinaZ# ""3 1$lhYa/W^cY^c\3 1lhYa/hZgk^XZ3 1"" L^i]^cV1lhYa/hZgk^XZ3iV\^hV1lhYa/edgi3edgi!l]^X]YZÄcZh i]ZXdccZXi^dced^ciidVLZWHZgk^XZVcY^ihHD6EW^cY^c\# ""3 1$lhYa/hZgk^XZ3 1$lhYa/YZÄc^i^dch3
281
282
CHAPTER
59
Creating and Consuming Web Services
Now that we have looked at the layout of WSDL and definitions of the tag elements that make up a document, we need to examine a simple WSDL document and get familiar with its syntax. To give us something for comparison with our WSDL document, here is an extremely simple ColdFusion Component (CFC) that is being deployed as a Web service. Listing 59.2 shows the Number-to-String Conversion Web service. C`jk`e^,0%) CjbZg^XHig^c\#X[X —Number-to-String Conversion Web Service 1""" 6JI=DG/7gZcYVcD¼=VgVWd]VgV5ZiZX]hdaji^dch#Xdb L:7H:GK>8:/CjbZg^XHig^c\#X[X 9:H8G>EI>DC/8daY;jh^dc8;8YZeadnZYVhVLZWHZgk^XZidgZijgc VeVhhZY"^c^ciZ\Zg^cid^ihHig^c\gZegZhZciVi^dc# 6G8:/H^beaZ8gZY^iGVi^c\#X[X 9:H8G>EI>DC/8daY;jh^dc8;8YZeadnZYVhVLZWHZgk^XZidgZijgc V8gZY^iGVi^c\¹hig^c\º[dgVeVhhZY"^cHdX^VaHZXjg^incjbWZg l]^X]^hVhig^c\gZegZhZciZYWni]ZVg\jbZci¹HHCº# """3 1X[XdbedcZcidjieji2º[VahZº3 1"""LZYZÄcZi]Z8;8¼hh^c\aZ[jcXi^dci]VigZig^ZkZhi]ZXgZY^i gVi^c\[dgVeVhhZY"^cHdX^VaHZXjg^incjbWZgVcYgZijgch^i"""3 1X[[jcXi^dccVbZ2º\Zi8gZY^iGVi^c\ºgZijgcIneZ2ºhig^c\ºdjieji2º[VahZº VXXZhh2ºgZbdiZº3 1"""I]ZckdXVi^dc:mXZei^dcº3 1hZfjZcXZ$3 1$XdbeaZmIneZ3 1$hX]ZbV3 1$lhYa/ineZh3 1lhYa/bZhhV\ZcVbZ2º\Zi8gZY^iGVi^c\GZhedchZº3 1lhYa/eVgicVbZ2º\Zi8gZY^iGVi^c\GZijgcºineZ2ºmhY/hig^c\º$3 1$lhYa/bZhhV\Z3 1lhYa/bZhhV\ZcVbZ2º8;8>ckdXVi^dc:mXZei^dcº3 1lhYa/eVgicVbZ2º[VjaiºineZ2ºich&/8;8>ckdXVi^dc:mXZei^dcº$3 1$lhYa/bZhhV\Z3 1lhYa/bZhhV\ZcVbZ2º\Zi8gZY^iGVi^c\GZfjZhiº3 1lhYa/eVgicVbZ2ºHHCºineZ2ºmhY/hig^c\º$3 1$lhYa/bZhhV\Z3 1lhYa/edgiIneZcVbZ2ºH^beaZ8gZY^iGVi^c\º3 1lhYa/deZgVi^dccVbZ2º\Zi8gZY^iGVi^c\ºeVgVbZiZgDgYZg2ºHHCº3 1lhYa/^cejibZhhV\Z2º^bea/\Zi8gZY^iGVi^c\GZfjZhiº cVbZ2º\Zi8gZY^iGVi^c\GZfjZhiº$3 1lhYa/djiejibZhhV\Z2º^bea/\Zi8gZY^iGVi^c\GZhedchZºcVbZ2º\Zi8gZY^iGVi^c\G ZhedchZº$3 1lhYa/[VjaibZhhV\Z2º^bea/8;8>ckdXVi^dc:mXZei^dcº cVbZ2º8;8>ckdXVi^dc:mXZei^dcº$3 1$lhYa/deZgVi^dc3 1$lhYa/edgiIneZ3 1lhYa/W^cY^c\cVbZ2ºH^beaZ8gZY^iGVi^c\#X[XHdVe7^cY^c\º ineZ2º^bea/H^beaZ8gZY^iGVi^c\º3 1lhYahdVe/W^cY^c\hinaZ2ºgeXºigVchedgi2º]iie/$$hX]ZbVh#mbahdVe#dg\$hdVe$ ]iieº$3 1lhYa/deZgVi^dccVbZ2º\Zi8gZY^iGVi^c\º3 1lhYahdVe/deZgVi^dchdVe6Xi^dc2ºº$3 1lhYa/^cejicVbZ2º\Zi8gZY^iGVi^c\GZfjZhiº3
Creating Web Services
C`jk`e^,0%. (continued) 1lhYahdVe/WdYnZcXdY^c\HinaZ2º]iie/$$hX]ZbVh#mbahdVe#dg\$hdVe$ZcXdY^c\$º cVbZheVXZ2º]iie/$$T*.#dlhºjhZ2ºZcXdYZYº$3 1$lhYa/^ceji3 1lhYa/djiejicVbZ2º\Zi8gZY^iGVi^c\GZhedchZº3 1lhYahdVe/WdYnZcXdY^c\HinaZ2º]iie/$$hX]ZbVh#mbahdVe#dg\$hdVe$ZcXdY^c\$º cVbZheVXZ2º]iie/$$T*.#dlhºjhZ2ºZcXdYZYº$3 1$lhYa/djieji3 1lhYa/[VjaicVbZ2º8;8>ckdXVi^dc:mXZei^dcº3 1lhYahdVe/[VjaiZcXdY^c\HinaZ2º]iie/$$hX]ZbVh#mbahdVe#dg\$hdVe$ZcXdY^c\$º cVbZ2º8;8>ckdXVi^dc:mXZei^dcºcVbZheVXZ2º]iie/$$T*.#dlhºjhZ2ºZcXdYZYº$3 1$lhYa/[Vjai3 1$lhYa/deZgVi^dc3 1$lhYa/W^cY^c\3 1lhYa/hZgk^XZcVbZ2ºH^beaZ8gZY^iGVi^c\HZgk^XZº3 1lhYa/edgiW^cY^c\2º^bea/H^beaZ8gZY^iGVi^c\#X[XHdVe7^cY^c\º cVbZ2ºH^beaZ8gZY^iGVi^c\#X[Xº3 1lhYahdVe/VYYgZhhadXVi^dc2º]iie/$$adXVa]dhi$dlh$*.$H^beaZ8gZY^iGVi^c\# X[Xº$3 1$lhYa/edgi3 1$lhYa/hZgk^XZ3 1$lhYa/YZÄc^i^dch3
Now when we look at this WSDL document, it should quickly be apparent what is important. On the line with the first 1lhYa/deZgVi^dc3 tag, we see the operation \Zi8gZY^iGVi^c\, which is the method clients will wish to invoke. On the next line we see that the input message is \Zi8gZY^iGVi^c\GZfjZhi, l]^X] is displayed on the first line with a 1lhYa/bZhhV\Z3 tag. It has a single 1lhYa/eVgi3 tag named HHC, which is of data type mhY/hig^c\. The message \Zi8gZY^iGVi^c\GZhedchZ describes the gZijgc variable and its data type. Our relatively simple CFC is now a powerful Web service that can be used by businesses around the world to access credit ratings for potential customers before deciding to extend credit to them. Listing 59.8 shows an example of ColdFusion consuming the H^beaZ8gZY^iGVi^c\ Web service; this action will also be reviewed later in this chapter. C`jk`e^,0%/ IZhiH^beaZ8gZY^iGVi^c\#X[b —Invocation Example with Simple Data Type 1""" 6JI=DG/7gZcYVcD¼=VgVWd]VgV5ZiZX]hdaji^dch#Xdb L:7H:GK>8:/IZhiH^beaZ8gZY^iGVi^c\#X[b 9:H8G>EI>DC/IZhii]Z8;8# """3 1"""8dchigjXii]ZJGAYncVb^XVaan"""3 1XÄ[cdiÄcYCd8VhZ¹]iiehº!X\^#hZgkZgTegdidXda3
289
290
CHAPTER
59
Creating and Consuming Web Services
C`jk`e^,0%/ (continued) 1X[hZii]ZJGA2¹]iie/$$º3 1X[ZahZ3 1X[hZii]ZJGA2¹]iieh/$$º3 1$XÄ[3 1"""6YYi]ZhZgkZgVcYXjggZcieVi]"""3 1X[hZii]ZJGA2i]ZJGAX\^#hZgkZgTcVbZ¹/ºX\^#hZgkZgTedgi X\^#hXg^eiTcVbZ3 1"""CdlgZbdkZi]^hÄaZ¼hcVbZ!l]^X]^hVii]ZZcY"""3 1X[hZii]ZJGA2a^hi9ZaZiZ6ii]ZJGA!a^hiAZci]ZJGA!º$º!¹$º3 1XÄckd`ZlZWhZgk^XZ2ºi]ZJGA$H^beaZ8gZY^iGVi^c\#X[X4lhYaº bZi]dY2º\Zi8gZY^iGVi^c\ºgZijgckVg^VWaZ2ºXgZY^iGVi^c\º3 1XÄckd`ZVg\jbZcicVbZ2ºHHCºkVajZ2º%%%%%%%%&º$3 1$XÄckd`Z3 1X[djieji3I]ZgZhjai^h/XgZY^iGVi^c\1$X[djieji3
Most of this script simply creates the i]ZJGA variable. This allows the script to run on any Web server and any directory. The script assumes that it lies in the same directory as the Web service. Once the URL is figured out, the script simply uses the 1XÄckd`Z3 tag to call it. Now let’s take a look at a similar CFC that takes a higjXi data type. While a higjXi is similar to a number of data types in C++ and Java, it does not exactly match any of those defined in the XML Schema used by WSDL and SOAP for data-type representation and conversion. Listing 59.9 shows the Credit Rating Web service, which for its only argument takes a bVe or ColdFusion structure as the data type for its only argument. C`jk`e^,0%0 BVe8gZY^iGVi^c\#X[X —Web Service with higjXi or bVe Data Type 1""" 6JI=DG/7gZcYVcD¼=VgVWd]VgV5ZiZX]hdaji^dch#Xdb L:7H:GK>8:/BVe8gZY^iGVi^c\#X[X 9:H8G>EI>DC/8daY;jh^dc8;8YZeadnZYVhVLZWHZgk^XZidgZijgc V8gZY^iGVi^c\hig^c\[dgVeVhhZY"^c¹EZghdcºhigjXi# 6GiZbº3 1hZfjZcXZ3 1ZaZbZcicVbZ2º`Znºc^aaVWaZ2ºigjZºineZ2ºmhY/VcnIneZº$3 1ZaZbZcicVbZ2ºkVajZºc^aaVWaZ2ºigjZºineZ2ºmhY/VcnIneZº$3 1$hZfjZcXZ3 1$XdbeaZmIneZ3 1XdbeaZmIneZcVbZ2ºBVeº3 1hZfjZcXZ3 1ZaZbZcibVmDXXjgh2ºjcWdjcYZYºb^cDXXjgh2º%ºcVbZ2º^iZbº ineZ2ºVeVX]ZhdVe/bVe>iZbº$3 1$hZfjZcXZ3 1$XdbeaZmIneZ3 1$hX]ZbV3
This bVe complex type is generated by all uses of the higjXi data type in 1X[[jcXi^dc3 arguments. You will notice that both the `Zn and kVajZ can be of any data type. A call to this Web service will work if it comes from a ColdFusion page, but it’s not the most platform-independent way of accepting structured data. Because ColdFusion doesn’t predefine data types for all variables, we need to be aware of data types that may be problematic. The higjXi or bVe data type common to ColdFusion is not exactly represented in the XML Schema that SOAP uses for automatic datatype translation. Another unsupported data type is fjZgn. That is why we need to limit the use of unsupported data types in Web services when interacting with other platforms.
;\Ôe`e^:fdgc\o;XkXKpg\j Web services may be significantly more complex than our “simple” example, and their input parameters may be custom or unsupported data types. A Web service may need to accept multiple fields, or a single field containing a complex data type, in order to process the called function and return data to the caller. Object-oriented languages such as Java, C++, and C# have direct mappings from their complex data types to the XML Schema data types used by SOAP and WSDL.
291
292
CHAPTER
59
Creating and Consuming Web Services
Unfortunately, ColdFusion doesn’t have direct mappings to many of these complex data types. What it does have is the capacity to let you define your own complex data types using CFCs and the 1X[egdeZgin3 tag. Listing 59.11 shows a CFC completely empty of content except for 1X[egdeZgin3 tags. C`jk`e^,0%(( 8gZY^iEZghdc#X[X —Complex Data Type for Use with a Web Service 1""" 6JI=DG/7gZcYVcD¼=VgVWd]VgV5ZiZX]hdaji^dch#Xdb 8DBEDC:CI/8gZY^iEZghdc#X[X 9:H8G>EI>DC/8daY;jh^dc8;8YZeadnZYVhVXdbeaZmYViVineZ[dg jhZl^i]LZWHZgk^XZh#Cd[jcXi^dch#CdVg\jbZcih# """3 1X[XdbedcZci3 1X[egdeZgincVbZ2º;^ghiCVbZºineZ2ºhig^c\º3 1X[egdeZgincVbZ2ºAVhicVbZºineZ2ºhig^c\º3 1X[egdeZgincVbZ2º6YYgZhhºineZ2ºhig^c\º3 1X[egdeZgincVbZ2º8^inºineZ2ºhig^c\º3 1X[egdeZgincVbZ2ºHiViZºineZ2ºhig^c\º3 1X[egdeZgincVbZ2ºO^e8dYZºineZ2ºhig^c\º3 1X[egdeZgincVbZ2ºHHCºineZ2ºhig^c\º3 1$X[XdbedcZci3
The 1X[egdeZgin3 tag is used for Web services to define a complex data type. In ColdFusion this would be a structure, but because a higjXi is not a supported data type, we use another CFC without arguments to define the structure of our complex data type. The Credit Rating CFC Web service using a complex data type is shown in Listing 59.12. C`jk`e^,0%() 8dbeaZm8gZY^iGVi^c\#X[X —Web Service with Complex Data Type 1""" 6JI=DG/7gZcYVcD¼=VgVWd]VgV5ZiZX]hdaji^dch#Xdb L:7H:GK>8:/8dbeaZm8gZY^iGVi^c\#X[X 9:H8G>EI>DC/8daY;jh^dc8;8YZeadnZYVhVLZWHZgk^XZidgZijgc V8gZY^iGVi^c\¹hig^c\º[dgVeVhhZY"^c¹EZghdcº!l]^X]^hV8dbeaZm 9ViVIneZl]^X]^hYZÄcZY^ci]Z8;8EZghdc#X[X# 6Gckd`Zi]ZlZWhZgk^XZ"""3 1XÄckd`ZlZWhZgk^XZ2ºi]ZJGA$CjbZg^XHig^c\#X[X4lhYaº bZi]dY2º^ciZ\ZgIdHig^c\ºcjbWZgCjbZg^X2ºgVcYGVc\Z%!.º gZijgcKVg^VWaZ2ºgZhjaiº3 1X[djieji3GZhjaid[lZWhZgk^XZXVaa/gZhjai1$X[djieji3 1e3 1"""cdlYdVh^beaZ8;8XVaa"""3 1XÄckd`ZXdbedcZci2ºCjbZg^XHig^c\º bZi]dY2º^ciZ\ZgIdHig^c\ºcjbWZgCjbZg^X2ºgVcYGVc\Z%!.º gZijgcKVg^VWaZ2ºgZhjaiº3 1X[djieji3GZhjaid[XdbedcZciXVaa/gZhjai1$X[djieji3
Once again, the script starts by figuring out the current root URL. After that, we use 1XÄckd`Z3 to call the CjbZg^XHig^c\ Web service. We tell the tag which method to execute, and we pass in the cjbWZgCjbZg^X attribute. Lastly, we tell the 1XÄckd`Z3 tag to return the result in a variable called gZhjai. The next use of 1XÄckd`Z3 calls the exact same code, except this time it is used as a ColdFusion component.
:fdgc\o;XkXKpg\j As we discussed previously, a complex data type can be described as a data type that represents multiple values. Arrays, record sets, and structures are good examples of complex data types. Although
297
298
CHAPTER
59
Creating and Consuming Web Services
these are relatively easy to visualize and describe, representing them programmatically among different application servers on different platforms presents a formidable obstacle. SOAP saves us from having to code our Web services to accommodate every server’s interpretation of every data type. This is accomplished by defining SOAP-specific data types that are a workable subset of common data types. The most that developers must do is plug their variables into the appropriate SOAP data types. Each application is responsible for translating to and from the SOAP data types. CFML contains several of these complex data types. As part of consuming Web services, you will need to know how ColdFusion converts WSDL-defined data types to ColdFusion data types and vice versa. In order to facilitate their uses in CFCs exposed as Web services, ColdFusion maps certain objects to their corresponding SOAP data types completely behind the scenes. Table 59.3 shows this mapping. KXYc\,0%* WSDL-to-ColdFusion Data Type Conversion WSDL DATA TYPE
COLDFUSION DATA TYPE
HD6E":C8/YdjWaZ
cjbZg^X
HD6E":C8/WddaZVc
WddaZVc
HD6E":C8/hig^c\
hig^c\
HD6E":C8/6ggVn
VggVn
mhY/WVhZ+)7^cVgn
W^cVgn
mhY/ÅdVi
cjbZg^X
mhY/ZcjbZgVi^dc
hig^c\
mhY/YViZI^bZ
YViZ
ich&/FjZgn7ZVc
fjZgn
kd^Y
Nothing is returned
Other complex type
structure
* These types do convert between ColdFusion and other SOAP implementations and are not supported directly by WSDL.
@emfZXk`fen`k_:fc[=lj`fe9l`c[\i When you add a Web service via the ColdFusion Builder Services Browser, ColdFusion Builder reads the WSDL document so that it can generate the invocation code for you. You never have to read the WSDL yourself! Figure 59.1 shows the Services Browser user interface for adding a Web service (to get to this dialog box, click the Show Web Services button in the Services Browser to see Web services that have been added and then click the red button). You point the ColdFusion Builder Services Browser to a WSDL document. ColdFusion Builder analyzes the WSDL and displays all the methods, and the arguments for each, supported by the Web service. To invoke a Web service method, place your cursor in your ColdFusion code at the location where you want the invocation code inserted and then, keeping the code window visible, right-click in the Services Browser on the name of the method you want to invoke and choose either Insert CFInvoke or Insert CreateObject from the menu that appears.
Consuming Web Services
=`^li\,0%( ColdFusion Builder Services Browser User Interface.
@emfb`e^%E\e\iXk\[NJ;C As you can probably imagine, the task of generating WSDL for a Web service takes time. Because of this, ColdFusion caches the WSDL generated by the Web service after the first time it is generated. There are two ways to deal with this. The ColdFusion Administrator provides a simple button you can use to refresh the WSDL generated by a Web service call. Also, the XÄckd`Z tag supports a gZ[gZh]LH9A attribute that you can use to force ColdFusion to refresh its WSDL definition. Another useful feature of XÄckd`Z in ColdFusion is lhYa'?VkV6g\h. If you are familiar with the WSDL2 Java tool that allows ColdFusion users to generate WSDL, you can specify a spacedelimited set of arguments that will be passed to this tool when XÄckd`Z is used. Most folks will never need to use this attribute, though.
299
300
CHAPTER
59
Creating and Consuming Web Services
Nfib`e^n`k_JF8GI\hl\jkj ColdFusion offers a variety of ways to work with the SOAP requests and responses involved in Web services. Let’s start with a simple example. As discussed earlier, for a component to be used as a Web service, it must have at least one method with VXXZhh2ºgZbdiZº. This same method, however, can be called by other ColdFusion templates on the server. It can also be called via Flash Remoting. What if you want to ensure that the method is only called as a Web service? ColdFusion has a function, ^hHdVeGZfjZhi, that returns igjZ if the current method was executed as a Web service. Listing 59.18 demonstrates a simple Web service with a method that can only be called as a Web service. C`jk`e^,0%(/ _jhiVlZWhZgk^XZ#X[X—A Web-Service-Only Component 1X[XdbedcZci3 1X[[jcXi^dccVbZ2ºiZhiºgZijgcineZ2ºhig^c\ºVXXZhh2ºgZbdiZº3 1XÄ[^hHdVeGZfjZhi3 1X[gZijgc¹XdjaYc¼iXVaai]ZbZi]dY# 1$X[XViX]3 1$X[ign3
As in the other templates we have used, the script begins by determining the current URL. Once past that, we invoke the Web service method and then call the same method as a local CFC. Since we know this isn’t going to work, we wrap it in a 1X[ign31X[XViX]3 block. When run, the Web service will return a good result, while the local CFC invocation will throw an error.
:Xcc`e^N\YJ\im`Z\jn`k_E`ccXYc\8i^ld\ekj When building a method, any combination of arguments can be used to define its behavior. Some Web services may define a method as having “nillable” arguments. This simply means the value can be null. However, ColdFusion doesn’t allow you to create null values. Thus in earlier versions of ColdFusion it was impossible to call these Web services. An argument, db^i, can be used in 1XÄckd`ZVg\jbZci3 to pass a null value to a Web service. Listing 59.19 demonstrates a simple Web service with an optional argument (this will act as a nillable argument). C`jk`e^,0%(0 C^aaVWaZLH#X[X —Nillable CFC Example 1X[XdbedcZci3 1X[[jcXi^dccVbZ2ºiZhiºgZijgcineZ2ºhig^c\ºVXXZhh2ºgZbdiZº3 1X[Vg\jbZcicVbZ2ºVae]VºineZ2ºhig^c\ºgZfj^gZY2ºigjZº3 1X[Vg\jbZcicVbZ2ºWZiVºineZ2ºhig^c\ºgZfj^gZY2º[VahZº3 1X[Vg\jbZcicVbZ2ºXVgcnºineZ2ºhig^c\ºgZfj^gZY2ºigjZº3 1X[gZijgc¹;ddº3 1$X[[jcXi^dc3 1$X[XdbedcZci3
This is an extremely simple Web service. The test method has three arguments. The second argument, WZiV, is marked as optional. Listing 59.20 demonstrates how we can correctly call this Web service. C`jk`e^,0%)' IZhiC^aaVWaZ#X[b —Testing C^aaVWaZLH#X[X 1"""8dchigjXii]ZJGAYncVb^XVaan"""3 1XÄ[cdiÄcYCd8VhZ¹]iiehº!X\^#hZgkZgTegdidXda3 1X[hZii]ZJGA2¹]iie/$$º3 1X[ZahZ3 1X[hZii]ZJGA2¹]iieh/$$º3 1$XÄ[3 1"""6YYi]ZhZgkZgVcYXjggZcieVi]"""3 1X[hZii]ZJGA2i]ZJGAX\^#hZgkZgTcVbZ¹/ºX\^#hZgkZgTedgi X\^#hXg^eiTcVbZ3 1"""CdlgZbdkZi]^hÄaZ¼hcVbZ!l]^X]^hVii]ZZcY"""3
301
302
CHAPTER
59
Creating and Consuming Web Services
C`jk`e^,0%)' (continued) 1X[hZii]ZJGA2a^hi9ZaZiZ6ii]ZJGA!a^hiAZci]ZJGA!º$º!¹$º3 1XÄckd`ZlZWhZgk^XZ2ºi]ZJGA$C^aaVWaZLH#X[X4lhYaºbZi]dY2ºiZhiº gZijgcKVg^VWaZ2ºgZhjaiº3 1XÄckd`ZVg\jbZcicVbZ2ºVae]VºkVajZ2º[ddº3 1XÄckd`ZVg\jbZcicVbZ2ºWZiVºdb^i2ºnZhº3 1XÄckd`ZVg\jbZcicVbZ2ºXVgcnºkVajZ2ºbddº3 1$XÄckd`Z3 1X[djieji3GZhjai^hgZhjai1$X[djieji3
As with our numerous other examples, we begin by simply grabbing the current URL dynamically. We then invoke the C^aaVWaZLH Web service. This Web service takes three arguments, with the middle argument, WZiV, being optional. By default, you cannot omit this argument, even though the method was defined as optional. With ColdFusion, however, we can pass in the argument and use db^i2ºnZhº to pass a null value to the Web service. Think of this as a simple way of passing a null value, which ColdFusion doesn’t natively support.
9\jkGiXZk`Z\j As with many technologies, architectures, and strategies, Web services have generated significant hype. Along with the advantages of cross-platform compatibility come some drawbacks. Although the distributed computing environment of Web services is widely recognized as the way of the future, it carries the baggage of network latency and additional translation time. The actual overhead of running a Web service is not as bad as perceived, but it is a factor for system architects to consider when selecting parts of their systems to expose to the world. Careful testing and optimization can reduce this potential problem significantly. Here are several general principles to consider when programming and architecting Web services: N
Use coarse-grained Web services. Do not call the same Web service 10 times on a page. Call it once and use a query of queries to return the granular information for display. Return the appropriate amount of information based on the transaction overhead.
N
Use stateless Web services whenever possible.
N
Limit the use of complex data types within a Web service when interacting with other platforms.
Another practice that is highly recommended is the use of asynchronous Web services. Synchronous RPC-style operations let you know immediately whether an operation was successful. Performing synchronous operations across multiple processes is an all-or-nothing proposition. The initiating application must wait for the chain of GZfjZhi"gZhedchZ operations, regardless of its length. When something goes down or a process fails, the application initiating the request must know to take some other course of action. On the other hand, asynchronous messaging allows a process to be concerned only with initiating a request, knowing that it will eventually receive a response asynchronously. This relieves the Web service client from waiting for the
Best Practices
invoked operation to respond. The DcZ"lVn and Hda^X^iVi^dc operation types are commonly used with asynchronous Web services. These should be used for performance reasons, when available from Web services providers, whenever immediate responses are not required.
ckdXVi^dc· :mXZei^dc that ColdFusion creates when generating the WSDL for your Web service. This allows someone who calls a Web service you have written to catch run-time or other errors while their code continues processing without the expected response from your Web service. Any Web service can throw errors, which may or may not be critical to the page that is calling the service. If you use 1X[ign3 and 1X[XViX]3 or the ign, XViX] 1X[hXg^ei> equivalents, you can catch CFC, SOAP, and other errors in your application. If you don’t catch these errors, they will be displayed in the browser. Unless you’re testing the Web service yourself, you probably don’t want the error to be written to the screen. Catching errors in ColdFusion is not difficult, but it does take some effort. You can catch multiple types of errors that may all require various types of additional processing. You can also specify an error type of Vcn, which acts as a catch-all to the ColdFusion HZVgX]HlZY^h]EZghdcº3 1XÄckd`ZVg\jbZcicVbZ2º[CVbZºkVajZ2ºHkZcº$3 1XÄckd`ZVg\jbZcicVbZ2ºaCVbZºkVajZ2ºHkZchhdcº$3 1XÄckd`ZVg\jbZcicVbZ2ºVYYgZhhºkVajZ2ºº$3 1XÄckd`ZVg\jbZcicVbZ2ºo^e8dYZºkVajZ2ºº$3 1XÄckd`ZVg\jbZcicVbZ2ºX^inºkVajZ2ºº$3 1$XÄckd`Z3 1X[XViX]ineZ2ºVcnº3 1X[hZiVhig^c\2¹L]ZgZ^ci]ZldgaY^hHkZcHkZchhdc4º3 1$X[XViX]3 1$X[ign3 1X[djieji3VHig^c\1$X[djieji3
:feÔ^li`e^N\YJ\im`Z\j`ek_\:fc[=lj`fe8[d`e`jkiXkfi The ColdFusion Administrator lets you register a Web service with a name and URL. When you reference that Web service later in your code, you won’t have to specify the URL for the Web service’s WSDL file. Instead, the Web service can be referenced using the name that points to the WSDL’s URL. For example, anytime you invoke a Web service registered as O^e8dYZLH on a particular server, you reference it as LZWHZgk^XZ2ºO^e8dYZLHº. The URL can then be changed to point to another URL without modifying the invocation code throughout the application. This represents a type of code encapsulation, which could also be done using 6EEA>86I>DC or G:FJ:HI scope variables.
303
This page intentionally left blank
:?8GK!8ViZ\dgnAVWZa!8ViZ\dgnHX]ZbZ!8ViZ\dgnIZgb! 8dbbZcih!8dciZci!8dciZciBdYZ!8dciZciHgX!8dciZciIneZ!8dcig^Wjidg:bV^a! 8dcig^WjidgCVbZ!8dcig^WjidgJG>!8gZViZY9ViZ!:me^gVi^dc9ViZ!>9!>9EZgbVa^c`! A^c`=gZ[!A^c`=gZ[AVc\!A^c`AZc\i]!A^c`GZa!A^c`I^iaZ!A^c`IneZ!EjWa^h]ZY9ViZ! G^\]ih!GHHA^c`!HdjgXZ!HdjgXZJGA!HjbbVgn!HjbbVgnBdYZ!HjbbVgnHgX!HjbbVgnIneZ! I^iaZ!I^iaZIneZ!JeYViZY9ViZ!JG>!MBA7VhZ
Lj`e^;lYc`e:fi\Xe[`Kle\j[i]ZgZXdgYgZegZhZcihVhjW[daYZg!a^hi^iVhVcdei^dc"""3 1XÄ[IneZZf¹9^gº3 1dei^dckVajZ2ºhjW[daYZgEVi]$CVbZº3CVbZ1$dei^dc3 1$XÄ[3 1$XÅdde3 1$hZaZXi3 1"""HjWb^iWjiidcidcVk^\ViZidi]ZhZaZXiZY[daYZg"""3 1^cejiineZ2ºhjWb^iºkVajZ2º\dº3 1$[dgb3
1"""JhZFjZgnd[FjZg^Zh>cBZbdgnFjZgnid\ZiVhjWhZid["""3 1"""i]ZfjZgngZijgcZYWn1X[Y^gZXidgn3#I]^hcZlfjZgndW_ZXi"""3 1"""l^aa]daYdcani]ZÄaZgZXdgYh!cdiVcnhjW[daYZggZXdgYh"""3 1X[fjZgnYWineZ2ºfjZgnºcVbZ2ºÄaZhFjZgnº3 H:A:8I;GDBY^gZXidgnFjZgn L=:G:INE:2»;^aZ¼ 1$X[fjZgn3
1""">[i]ZgZ^hViaZVhidcZÄaZidY^heaVn###"""3 1XÄ[ÄaZhFjZgn#gZXdgY8djci\i%3 1"""9^heaVni]ZÄaZh^cVh^beaZ=IBAiVWaZ"""3 1iVWaZl^Yi]2º*%%ºWdgYZg2º%ºXZaaEVYY^c\2º&ºXZaaHeVX^c\2º%º3 1igW\Xdadg2ºXdgcÅdlZgWajZº3 1i]3;^aZcVbZ1$i]3 1i]3BdY^ÄZY1$i]3 1i]3H^oZ1$i]3 1$ig3 1""";dgZVX]ÄaZ###"""3 1XÅddefjZgn2ºÄaZhFjZgnº3 1"""JhZVaiZgcVi^c\Xdadgh[dgi]ZiVWaZgdlh"""3 1XÄ[ÄaZhFjZgn#XjggZciGdlbdY'Zf%3 1X[hZigdl8dadg2¹a^\]i\gZnº3 1X[ZahZ3 1X[hZigdl8dadg2¹l]^iZº3 1$XÄ[3 1"""9^heaVni]ZÄaZYZiV^ah"""3 1igW\Xdadg2ºgdl8dadgº3 1""";^aZcVbZ"""3 1iYl^Yi]2º'*%º3 CVbZ 1$iY3 1""";^aZbdY^ÄXVi^dcYViZVcYi^bZ"""3 1iYl^Yi]2º'%%º3
339
340
CHAPTER
61
Interacting with the Operating System
C`jk`e^-(%(+ (continued) YViZ;dgbVi9ViZAVhiBdY^ÄZY!¹b$Y$nnnnº Vi i^bZ;dgbVi9ViZAVhiBdY^ÄZY!¹]/bb/hhiiº 1$iY3 1""";^aZh^oZ"""3 1iYl^Yi]2º*%ºVa^\c2ºg^\]iº3 XZ^a^c\H^oZ$&%')@7 1$iY3 1$ig3 1$XÅdde3 1$iVWaZ3 1$XÄ[3 1$WdYn3 1$]iba3 1$X[djieji3
First, the ZmeVcYEVi] function is used to create a variable called WVhZ;daYZg that holds the path to the dlh folder on your server’s drive. The actual value of this variable when your page executes will likely be X/QXdaY[jh^dc.QlllgddiQdlh, X/Q^cZiejWQlllgddiQdlh, or something similar, depending on the Web server you’re using. For common sense security reasons, the user will only be able to explore files and directories within the WVhZ;daYZg. If you want the user to be able to explore some other folder, perhaps outside of your server’s document root, you can hard-code the WVhZ;daYZg variable with the location of that folder. Next, the 1X[eVgVb3 tag is used to declare a variable named hjW[daYZgEVi] and give it a default value of an empty string. This variable will indicate which subfolder within the WVhZ;daYZg that the user wants to explore. If a jga or [dgb parameter called hjW[daYZgEVi] is provided to the page, that value will be used; otherwise it’s assumed that the page is appearing for the first time. If the user has selected the subfolder named images, then the value of hjW[daYZgEVi] will be $^bV\Zh. The [daYZgId9^heaVn variable is then created by concatenating the WVhZ;daYZg together with the hjW[daYZgEVi]. This variable, then, holds the full path to the folder the user wants to explore; this is what will be supplied to the 1X[Y^gZXidgn3 tag to obtain the contents of the folder. So if the user has selected the subfolder named images, the value of [daYZgId9^heaVn will be X/QXdaY[jh^dc.Q lllgddiQdlhQ^bV\Zh,X/Q^cZiejWQlllgddiQdlhQ^bV\Zh, or something similar, depending on what ColdFusion edition or Web server you are using. Now the 1X[Y^gZXidgn3 tag can be used to get a listing of all the files and subfolders within the selected folder. This will result in a query object called Y^gZXidgnFjZgn, which will contain the columns listed in Table 61.7. Near the middle of this listing, a 1XÅdde3 tag is used to loop over the Y^gZXidgnFjZgn query, generating an 1dei^dc3 tag for each subfolder within the current folder. Within the loop, a 1XÄ[3 test is used to only output options for rows where the IneZ column is set to 9^g. This step is necessary because the query object may contain rows for subfolders and other rows for individual files. The 1XÄ[3 test effectively filters the query object so that only rows that represent folders are processed.
Working with Virtual Files
Another way to filter a directory query object by type (that is, to only include files or folders) is to use ColdFusion’s Query of Queries feature (also called In Memory Query). This strategy is used in the second half of this listing, to create a filtered version of Y^gZXidgnFjZgn (called ÄaZhFjZgn) that only contains records for files, not subfolders. Once that’s done, outputting the actual information about files is simple. A 1XÅdde3 block is used to output the file information in a simple HTML table, displaying the values of each record’s CVbZ, H^oZ, and 9ViZAVhiBdY^ÄZY columns. Note that the ordinary YViZ;dgbVi, i^bZ;dgbVi, and XZ^a^c\ functions are used to display the data attractively.
Nfib`e^n`k_M`iklXc=`c\j So far, we’ve discussed how you can use various ColdFusion tags and functions to work with files and directories on the server’s file system. From time to time, applications need to work with files of a temporary nature. For example, you may allow someone to upload a file to be used for a profile picture. The file is uploaded to a temporary folder (hopefully outside the Web root!) and checked to see if the file contains a valid image. After that is confirmed, the image can be resized. Finally, the image is moved to its permanent location somewhere under the Web server root so everyone can see it. So here’s the question: While the file is being checked and resized, does it need to actually exist on the file system? The answer is no. ColdFusion 9 introduces the concept of a completely virtual file system. This feature, called both in-memory files and the virtual file system (VFS), is a RAM-based file system. In every way, it acts like a real file system, but the actual data of the files is stored in your server’s RAM. How do you use this file system? In general, nothing special is needed to make use of it. You do have to ensure that it is enabled, though. The ColdFusion Administrator Settings page contains a new setting, Enable In-Memory File System. This must be enabled to make use of the new file system. Also notice that there is a limit to the total amount of data you can put on this file system. The total is configurable in the Administrator and defaults to 100 megabytes. Luckily, both of these settings are available via ColdFusion itself. This means that you can write code that uses the virtual file system only if it is actually enabled. After you’ve determined that you can use the in-memory file system, the only change you need to make is to use the gVb/$$ path as the root of your file or directory operations. So a real file may have a path that looks like this: $A^WgVgn$LZWHZgkZg$YdXjbZcih$[dd#X[b
And a virtual file would have a path that looks like this: gVb/$$$iZbeVeea^XVi^dcÄaZh$^bV\ZjeadVYh$[dd#_e\
Essentially, the use of gVb/$$ signifies that the path that follows is virtual and not one that exists on a physical disk. Listing 61.15 demonstrates a simple example that reads from and writes to the virtual file system.
341
342
CHAPTER
61
Interacting with the Operating System
C`jk`e^-(%(, k[h[b —Working with the Virtual File System 1""" ;^aZcVbZ/k[h[b 6ji]dg/GVnbdcY8VbYZc EjgedhZ/9ZbdchigViZhi]Zk^gijVaÄaZhnhiZb# """3 1X[hZibn;^aZ2¹gVb/$$$dlhÄaZh$iZhi#imiº3 1X[hZibn;daYZg2\Zi9^gZXidgn;gdbEVi]bn;^aZ3 1XÄ[cdiY^gZXidgn:m^hihbn;daYZg3 1X[Y^gZXidgnVXi^dc2ºXgZViZºY^gZXidgn2ºbn;daYZgº3 1$XÄ[3 1XÄ[cdiÄaZ:m^hihbn;^aZ3 1X[djieji3 1e3 I]ZÄaZ!bn;^aZ!^hXjggZcianZbein#1Wg$3 GZadVYi]^heV\Z 1$e3 1$X[djieji3 1X[ZahZ3 1X[hZiXdciZcih2ÄaZGZVYbn;^aZ3 1X[djieji3 1egZ3 XdciZcih 1$egZ3 1$X[djieji3 1$XÄ[3 1"""6eeZcYViZmibZhhV\Zidi]ZÄaZ"""3 1X[ÄaZVXi^dc2ºVeeZcYºÄaZ2ºbn;^aZºdjieji2ºIZbehij[[lg^iiZcidÄaZdccdlº3
Listing 61.15 begins by defining the path to our virtual file. The decision to use dlhÄaZh as a folder was somewhat arbitrary, but remember that since the virtual file system uses RAM, all templates on the server will share it. We first check to see whether the folder exists. If it doesn’t, the folder is created. Next we see if the file exists. If it does, it is read in and displayed. Finally we append a simple message to the end of the file. It is important to note that almost nothing about this template is any different from the template for a “normal” file or directory. The one single thing special is that use of the gVb/$$ path. As mentioned earlier, it is possibly to programmatically tell whether the virtual file system is enabled, as well as how large it can be, how much is being used, and how much space is left. Listing 61.16 is a modified version of the file explorer in Listing 61.14. What’s incredible is that the main modification (switching from a real file system to a virtual one) was accomplished with this one line: 1X[hZiWVhZ;daYZg2¹gVb/$$º3
C`jk`e^-(%(- k[hZmeadgZg#X[b —Exploring the Virtual File System 1""" ;^aZcVbZ/k[hmeadgZg#X[b 6ji]dg/CViZLZ^hhCBL!bdY^ÄZYWnGVn
Working with Virtual Files
C`jk`e^-(%(- (continued) EjgedhZ/Egdk^YZhVc^ciZg[VXZ[dgZmeadg^c\ÄaZhVcYhjW[daYZgh l^i]^ci]Zdlhgddi """3 1X[hZik[h>c[d2\ZiK;HBZiV9ViV¹gVbº3 1XÄ[cdik[h>c[d#ZcVWaZY3 1e3 Hdggn!Wjii]Zk^gijVaÄaZhnhiZb^hcdiZcVWaZY 1$e3 1X[VWdgi3 1$XÄ[3 1X[hZiWVhZ;daYZg2¹gVb/$$º3 1X[eVgVbcVbZ2ºhjW[daYZgEVi]ºineZ2ºhig^c\ºYZ[Vjai2ºº3 1X[hZi[daYZgId9^heaVn2WVhZ;daYZghjW[daYZgEVi]3 1X[Y^gZXidgnY^gZXidgn2º[daYZgId9^heaVnºcVbZ2ºY^gZXidgnFjZgnºhdgi2ºCVbZ6H8º ÄaiZg2ºº3 1X[djieji3 1]iba3 1]ZVY31i^iaZ3K^gijVa;^aZ:meadgZg1$i^iaZ31$]ZVY3 1WdYn3 1](3K^gijVa;^aZ:meadgZg1$](3 1e3 I]Zk^gijVaÄaZhnhiZb]VhVa^b^icjbWZg;dgbVik[h>c[d#a^b^iWniZh VcY^hXjggZcianjh^c\cjbWZg;dgbVik[h>c[d#jhZYWniZh# I]ZgZVgZcjbWZg;dgbVik[h>c[d#[gZZWniZhaZ[i# 1$e3 1[dgbVXi^dc2ºk[hZmeadgZg#X[bºbZi]dY2ºedhiº3 1XÄ[hjW[daYZgEVi]:F¹º3 NdjVgZVii]ZideaZkZa#1Wg3 1X[ZahZ3 8jggZci;daYZg/hjW[daYZgEVi]1Wg3 1$XÄ[3 HZaZXi[daYZg/ 1hZaZXicVbZ2ºhjW[daYZgEVi]ºdcX]Vc\Z2ºi]^h#[dgb#hjWb^iº3 1XÄ[a^hiAZchjW[daYZgEVi]!¹$º\i%3 1X[hZieVgZci;daYZg2a^hi9ZaZiZ6ihjW[daYZgEVi]!a^hiAZchjW[daYZgEVi]! ¹$º!¹$º3 1dei^dckVajZ2ºeVgZci;daYZgº3PeVgZci[daYZgR1$dei^dc3 1$XÄ[3 1XÅddefjZgn2º9^gZXidgnFjZgnº3 1XÄ[IneZZf¹9^gº3 1dei^dckVajZ2ºhjW[daYZgEVi]$CVbZº3CVbZ1$dei^dc3 1$XÄ[3 1$XÅdde3
343
344
CHAPTER
61
Interacting with the Operating System
C`jk`e^-(%(- (continued) 1$hZaZXi3 1^cejiineZ2ºhjWb^iºkVajZ2º\dº3 1$[dgb3 1X[fjZgnYWineZ2ºfjZgnºcVbZ2ºÄaZhFjZgnº3 H:A:8I;GDBY^gZXidgnFjZgn L=:G:INE:2»;^aZ¼ 1$X[fjZgn3 1XÄ[ÄaZhFjZgn#gZXdgY8djci\i%3 1iVWaZl^Yi]2º*%%ºWdgYZg2º%ºXZaaEVYY^c\2º&ºXZaaHeVX^c\2º%º3 1igW\Xdadg2ºXdgcÅdlZgWajZº3 1i]3;^aZcVbZ1$i]3 1i]3BdY^ÄZY1$i]3 1i]3H^oZ1$i]3 1$ig3 1XÅddefjZgn2ºÄaZhFjZgnº3 1XÄ[ÄaZhFjZgn#XjggZciGdlbdY'Zf%3 1X[hZigdl8dadg2¹a^\]i\gZnº3 1X[ZahZ3 1X[hZigdl8dadg2¹l]^iZº3 1$XÄ[3 1igW\Xdadg2ºgdl8dadgº3 1iYl^Yi]2º'*%º3 CVbZ 1$iY3 1iYl^Yi]2º'%%º3 YViZ;dgbVi9ViZAVhiBdY^ÄZY!¹b$Y$nnnnº Vi i^bZ;dgbVi9ViZAVhiBdY^ÄZY!¹]/bb/hhiiº 1$iY3 1iYl^Yi]2º*%ºVa^\c2ºg^\]iº3 XZ^a^c\H^oZ$&%')@7 1$iY3 1$ig3 1$XÅdde3 1$iVWaZ3 1$XÄ[3 1$WdYn3 1$]iba3 1$X[djieji3
In addition to the change to the WVhZ;daYZg variable, the code used a \ZiK;HBZiV9ViV call. This function takes one parameter, which must always be G6B . It returns a structure of information about the virtual file system. Keys include ZcVWaZY, a^b^i, [gZZ, and jhZY. The ZcVWaZY key is used in the listing to check whether the virtual system can be browsed at all. Later, the a^b^i, [gZZ, and jhZY keys are used to display the space usage for the system.
Executing Programs on the Server with
CI3 enables the printing of PDF documents from ColdFusion. These can be static files or PDFs created using ColdFusion tags such as 18;9D8JB:CI3 and 18;E9;3. We’ll also review related features such as the \ZiEg^ciZg>c[d function and the ColdFusion Administrator’s System Information page, which allow us to retrieve information about available printers and their capabilities for use in 18;EG>CI3, using X[eg^ci#ad\ and using 18;I=G:693.
Fm\im`\n There are many ways to create PDF files in ColdFusion, whether in the latest release or in previous ones. ColdFusion makes it very easy to manipulate PDF documents using tags such as 18;E9;3 and 18;E9;;DGB3. You can even create interactive PDF forms with a combination of 18;;DGB3 and 18;9D8JB:CI3 or by way of Document Description XML (DDX) used by Adobe LiveCycle Assembler or the 18;E9;3 tag. ColdFusion also offers various means of creating PDFs, including building them dynamically from CFML using 18;9D8JB:CI3 and with ColdFusion Report Builder and 18;G:EDGI3.
356
CHAPTER
62
Server-Side Printing
Further, developers have long found third-party solutions to help build PDFs. Also, static PDF files may exist or be created on the server by other means. They can be created by other processes on the server, or be placed on the server by some other operation, or even be uploaded to the server by end users. Whatever the situation, a common requirement is the capability to print the document on a printer attached to the server, and 18;EG>CI3makes this possible. allows a developer to control the number of pages printed, the size of paper used for printing, whether to print in color, and more. In fact, you can control any printing options that a given printer supports, including stapling, multiple pages per side, rotation, orientation, scaling, and print quality. You can also provide a password for encrypted pages. And with the power of the new 18;I=G:693 tag, you can even spool a print task to be processed asynchronously so that the CFML page launching the print job need not wait for its completion and risk timing out.
18;EG>CI3
Here are just a few possible scenarios that can make use of server-side printing: N
Generate order sheets when online orders are placed.
N
Generate invoices, packing slips, testing documents, and legal documents.
N
Manage electronic medical records and insurance claims and generate such documents on demand or as nightly reports.
One user described another scenario: Imagine a college (or similar institution) offering a means for its applicants to file online the necessary forms, references, cover letters, and so on; then all that information is printed for review when applications are considered. Though the printer must be defined on or be accessible to the server running ColdFusion, it doesn’t necessarily have to be physically attached to it. It could be connected via the network, including a WAN. This means it could enable N
Printing to a remote printer in another location that is connected to the server network via IP address, such as a remote warehouse
N
Printing to a broadcast printer, which in turn prints at several different workstation printers
Again, because we’re talking about printing to a server-side printer and not an end user’s printer, this doesn’t involve integration with the browser, which eliminates some common challenges. The simplicity of 18;EG>CI3will be a welcome alternative to those who have previously created a concoction of steps such as use of 18;:M:8JI:3 and of batch files to open Acrobat Reader to effect PDF printing.
Lj`e^18;EG>CI3 The simplest form of syntax for 18;EG>CI3 is as follows: 1X[eg^cihdjgXZ2ºhdbZÄaZ#eY[º3
Controlling Printer Capabilities
The hdjgXZ attribute points to a file, and unlike other 18;;>A:3 actions, the hdjgXZ attribute can name either a relative or absolute path. A relative path would be relative to the page issuing the tag. The hdjgXZ attribute could also point to a variable holding the result of some previous ColdFusion tag that created, read in, or manipulated a PDF.
Gi`ek`e^kfk_\;\]XlckGi`ek\i The simplest form of 18;EG>CI3 sends the named file (or a variable value, if used) to the default printer—that is, the default printer for the operating system account running ColdFusion. How do you find out what that default printer is and how to refer to it? There are at least two ways. First, the ColdFusion Administrator page, System Information, has a section called Printer Details that lists the default printer along with the names of all available printers. Also, the function \ZiEg^ciZg>c[d can be called with the name of one of those printers as its argument, or it can be called with no argument, in which case it returns information about the default printer. In either case, the structure it returns contains several keys, one of which is the eg^ciZg key, which displays the name of the selected printer. Therefore, the following line of code can be used to quickly and easily show what the system reports to be the default printer, if any: 1X[YjbekVg2º\Zieg^ciZg^c[d#eg^ciZgº3
The features for obtaining additional information about printers will be discussed further throughout this chapter.
Gi`ek`e^kf8efk_\iGi`ek\i Although the simple example just presented printed to the default printer, you can print just as easily to another printer if you know its name. You learned in the last section that the ColdFusion Administrator offers a way to see the names of available printers. If you have a printer on your server called HP LaserJet 2200 Series PCL 6, you can print the same document to it using this code: 1X[eg^cihdjgXZ2ºhdbZÄaZ#eY[ºeg^ciZg2º=EAVhZg?Zi''%%HZg^ZhE8A+º3
If instead you want to print to an available network printer named NTN-2W-HP_BW02 as found on server s1001prn02, you can print to it by forming a UNC path for the server and printer, as follows: 1X[eg^cihdjgXZ2ºhdbZÄaZ#eY[ºeg^ciZg2ºQQh&%%&egc%'QCIC"'L"=ET7L%'º3
EFK
CI3 tag, but most printers offer a wide range of capabilities to more precisely control the appearance of the printed page.
357
358
CHAPTER
62
Server-Side Printing
Some of these capabilities are generic (number of copies to print, pages to print, and so on), and others are printer specific. This section introduces these kinds of printer control capabilities.
Gi`dXip18;EG>CI38kki`Ylk\j Table 62.1 presents the attributes of 18;EG>CI3that apply to all printers. KXYc\-)%( Attributes of the 18;EG>CI3 Tag ATTRIBUTE
DESCRIPTION
hdjgXZ
Absolute or relative pathname to a PDF file or a PDF document variable
Viig^WjiZHigjXi
ColdFusion structure that contains attribute key-value pairs
Xdadg
nZh or cd (defaults to cd)
Xde^Zh
Number of copies (defaults to &)
ÄYZa^in
nZh or cd (defaults to cd)
eV\Zh
Page or pages to print (defaults to Vaa)
eVeZg
Options are aZiiZg, aZ\Va, 6), 6*, 7), 7*, 7)"?>H, 7*"?>H, and any media supported by the printer
eVhhldgY
PDF source file owner or user password
eg^ciZg
String that specifies the printer name
ineZ
E9;
Even though most of these options are generic and obvious, there are still some aspects of printerspecific behavior to notice. For instance, the default settings for some of the attributes listed in Table 62.1 may be printer dependent, and if you may try (mistakenly) to use attributes or values that are inappropriate, the available ÄYZa^in attribute can assist in protecting against such mistakes, as discussed in the next section.
Gi`ek\i$;\g\e[\ek8kki`Ylk\j Your printer may support many more attributes than those listed in Table 62.1: options to control two-sided printing, stapling, reversal of the page order, and much more. These special attributes can be discovered using the \ZiEg^ciZg>c[d function. Note, though, that you can’t use these printer-dependent attributes on the 18;EG>CI3 tag. Instead, you must specify them by way of the Viig^WjiZHigjXi attribute (and only by way of this attribute), as will be discussed later.
CI3 explains the purpose of many of these other attributes and their values. Note that the some of the results of \Zieg^ciZg^c[d show different values even for attributes listed in Table 62.1 (such as for eVeZg, which shows that the printer supports a (m* value, which was not listed previously). We can also see in the dump a YZ[Vjaih structure nested within the result, and it shows defaults for both those attributes in Table 62.1 and the additional attributes unique to this printer.
GXjj`e^Gi`ek\i$;\g\e[\ek8kki`Ylk\jn`k_6iig^WjiZHigjXi Now that we have the available attributes for the capabilities of this printer, we can pass them to the 18;EG>CI3 tag, but we can’t simply list them as attributes of the tag, as we can those in Table 62.1. Instead, these nonstandard attributes must be passed in using the special Viig^WjiZHigjXi attribute. The following example will help demonstrate this concept. If you want to print the first 16 pages of a document as two-sided on your printer, you can use the following: 1X[hZiVHZi2ph^YZh2ºild"h^YZY"adc\"ZY\Zº!eV\Zh2º&"&+ºr3 1X[eg^cihdjgXZ2ºhdbZWdd`#eY[ºViig^WjiZHigjXi2ºVHZiº3
359
360
CHAPTER
62
Server-Side Printing
Notice that we’re creating a structure, called VHZi (using ColdFusion’s ability to create structures implicitly rather than with HigjXiCZl). In it, we’re placing two keys: the attributes h^YZh and eV\Zh set to the desired values. EFK
CI3Xe[Viig^WjiZHigjXi#`en_`Z_ZXj\k_\Xkki`Ylk\j]fik_\kX^fm\ii`[\k_fj\`e k_\jkilZkli\%
K_\ÄYZa^in8kki`Ylk\ ColdFusion provides the flexibility to create and use attributes that may or may not be supported by a given printer, but this flexibility can also require management. Among the attributes listed in Table 62.1 is one whose purpose may not be self-evident: ÄYZa^in. This attribute indicates whether the attribute values specified must match exactly what the printer supports. For instance, although 7) is listed as a value for eVeZg in Table 62.1, it’s not listed as a valid value in the output the dump of the sample printer’s supported eVeZg values shown in Figure 62.1. If you specify ÄYZa^in2ºnZhº, the print attempt will fail with a traditional ColdFusion error: :ggdgDXXjggZYL]^aZEgdXZhh^c\GZfjZhi >ckVa^YbZY^VdgeVeZg[dgi]ZX[eg^ciiV\# :ggdg/BZY^V^hd"W)^hcdikVa^Ydc7gdi]ZgB;8"-+)%9Eg^ciZg#6kV^aVWaZbZY^V VgZ^hd"V)!cV"aZiiZg!cV"aZ\Va!ZmZXji^kZ!^hd"V*!^hd"V+!^hd"W*!^hd"W+!cV"cjbWZg" &%"ZckZadeZ!^hd"YZh^\cViZY"adc\!^hd"X*!bdcVgX]"ZckZadeZ!Dg\Vc^oZg?!Dg\Vc^oZg @!^ckd^XZ!6)Adc\!(m*![da^d!JhZg9ZÄcZY!^hd"V(!iVWad^Y!_^h"W)!6jidbVi^X";ZZYZg!ide!BE IgVn!bVcjVa
If you specify ÄYZa^in2ºcdº, however, the printer will make a reasonable attempt to print the job using the provided settings. The ÄYZa^in attribute is optional and defaults to cd.
AXmXGi`ekJ\im`Z\jXe[8kki`Ylk\j Besides being dependent on the printer, the particular printer attributes supported also depend on the operating system and network printer server, if there is one, as well as Java Print Service (JPS), on which the 18;EG>CI3 tag is based. Many printers support attributes that are not accessible from JPS. For example, according to the ColdFusion documentation, “the JPS for a Macintosh OS X running JDK 1.5 supports the fewest printer attributes. Upgrading to JDK 1.6 adds some functionality, but finishing attributes are still not supported.”
8[[`k`feXc18;EG>CI38kki`Ylk\j In addition to the list of tag attributes in Table 62.1 and any printer-specific attributes obtained via the \Zieg^ciZg^c[d function, a subset of the attributes for 18;EG>CI3 listed in the CFML Reference work even when ÄYZa^in2ºnZhº, though they’re not listed in the \Zieg^ciZg^c[d result. These include: VjidGdiViZ6cY8ZciZg, eV\ZHXVa^c\, gZkZghZEV\Zh, and jhZE9;EV\ZH^oZ. See the CFML Reference for more details on the uses and values for these attributes.
Determining Available Printers
;\k\id`e`e^8mX`cXYc\Gi`ek\ij The section “Printing to the Default Printer” discussed how to determine and print to the default printer for your system, and the section “Printing to Another Printer” showed you how to print to another printer, whether on the computer running ColdFusion or on another server on your network. How do you determine what other printers are available?
;\k\id`e`e^8mX`cXYc\Gi`ek\ij Of course, you can use your operating system–provided mechanisms to list available printers. If your application server runs on Windows, for instance, you can generally use Start > Printers and Faxes. But you can also obtain the list of printers from the ColdFusion Administrator’s Server Settings > Settings Summary page, as shown in Figure 62.2. This figure also highlights the portion of the report showing the printers defined on this server. =`^li\-)%) Available printers shown on the ColdFusion Administrator Settings Summary page.
Note that this list shows only the printers’ names, not their capabilities. For that, you must pass the printer name to the \ZiEg^ciZg>c[d function, like this: 1X[YjbekVg2º\Zieg^ciZg^c[d¹=EAVhZg?Zi''%%HZg^ZhE8A+ºº3
This will result in a dump of a structure as shown in Figure 62.1. K@G
PflZXeXcjffYkX`ek_\c`jkf]XmX`cXYc\gi`ek\ijgif^iXddXk`ZXccp%:fc[=lj`fe[f\jefkZlii\ekcp gifm`[\XYl`ck$`e]leZk`fe ]fik_`jgligfj\#Ylk9\e=fikX_Xjni`kk\eXe`]kpZljkfdkX^k_XkZXegifm`[\k_\`e]fidXk`fe%@ki\c`\jfeXele[fZld\ek\[ X daY[jh^dc#eg^ci#Eg^ciZg>c[dZcXjj`eAXmX%8jcfe^Xjpfl_Xm\eËk[`jXYc\[jlZ_`ek\ieXcAXmXfYa\Zkj`ek_\:fc[$ =lj`fe8[d`e`jkiXkfi#pflZXelj\k_`jZljkfdkX^#n_`Z_pflZXefYkX`eXk]iie/$$lll#XÅ^W#dg\$jY[#X[b4^Y2&,-'%
361
362
CHAPTER
62
Server-Side Printing
N_Xk8YflkFk_\iGi`ek\ij6 If you want to print to a printer that’s not listed on the System Information page, you must add the printer using your operating system mechanism for adding printers. ColdFusion offers no means to do this independently. As mentioned previously, however, if the printer is available on another printer on your network, you can print to that printer by forming a UNC path to name the server and printer, as shown in the section “Printing to Another Printer” earlier in this chapter.
Gi`ek\iG\id`jj`fej Because ColdFusion relies on the operating system to control the available printers, it is also subject to security permissions that may be defined for the printers. Even if a printer is configured locally on the system, the printer will not be available if the account under which ColdFusion is running does not have the proper permissions. By default, ColdFusion installs and runs as the Local System account (or “nobody” on Linux and Unix), which may not have printer access rights. For information on running ColdFusion as a specific user, see the following tech note: ]iie/$$`W'#VYdWZ#Xdb$Xeh$&,'$icT&,',.#]iba.
I\cXk\[=\Xkli\j Before concluding coverage of 18;EG>CI3, there are a few additional topics worth noting.
Gi`ekCf^ Whenever you print a document using 18;EG>CI3, ColdFusion logs the action (and some types of failures) to a eg^ci#ad\ file that appears in the standard 1XdaY[jh^dc3$ad\h directory. You can also view the logs using the ColdFusion Administrator, on the Log Files page, in the Debugging and Logging section. For each printed file, two lines will be created, tracking the date, time, application name, and thread ID as well as details such as the following: ¹Eg^ci_dW»hdbZWdd`#eY[¼hiVgiZY#Eg^ciZg»7gdi]ZgB;8"-+)%9Eg^ciZg¼#º ¹Eg^ci_dW»hdbZWdd`#eY[¼lVhhZciideg^ciZg#Eg^ciZg/»7gdi]ZgB;8"-+)%9Eg^ciZg¼# IdiVaeV\Zh/'#º
This log information can be very helpful when you’re trying to diagnose printing problems or confirm successful printing.
Lj`e^18;I=G:693 Because the process of sending a print job to a printer (or more typically, to your operating system’s print spooling service) may take some time, you can configure your code so that you don’t need to wait for the completion of that process of sending the job to the printer. This is a great use for the ColdFusion tag 18;I=G:693.
Related Features
You can run a print job asynchronously (meaning without waiting for completion of its transmission to the printer or spool) by enclosing the 18;EG>CI3 tag within a 18;I=G:693 tag block, as the following example shows: 1X[i]gZVYcVbZ2ºeg^ciº3 1X[eg^cihdjgXZ2ºhdbZÄaZ#eY[ºeg^ciZg2ºQQh&%%&egc%'QCIC"'L"=ET7L%'º3 1$X[i]gZVY3
¨ J\\:_Xgk\i)-#ÈDXeX^`e^K_i\X[j#É`e8[fY\:fc[=lj`fe0N\Y8ggc`ZXk`fe:fejkilZk`feB`k#Mfcld\)18ggc`ZXk`fe;\m\cfg$ d\ek#]fidfi\[\kX`cjfe18;I=G:693%
Gi`ek`e^Fk_\ik_XeG;=j As has been made clear from the beginning of this chapter, the 18;EG>CI3 tag can be used only to print PDF files. That may seem a severe limitation, and you may rightfully say, “What if I have some HTML or other content that I want to print?” Remember that ColdFusion offers the 18;9D8JB:CI3 tag, which enables you to create a PDF file from HTML that you dynamically create using CFML. And even if you don’t have an existing PDF file that you need to print, recall that various tags in ColdFusion can create PDF files that you may want to print, including the results of ColdFusion Report Builder (with 18;G:EDGI3), 18;E9;3, 18;E9;;DGB3, and more. See Chapter 28, “Working with PDF Files,” in Volume 2 for more information.
363
This page intentionally left blank
:?8GK;N, BD9>;N9C , or 9:A:I:. If none is specified, the default is FJ:GN.
C6B:
Required if 68I>DC2ºFjZgnº. This represents the name of the query object returned from the 18;A96E3 query.
H:GK:G
Required. The address hosting the LDAP server. Entries may be in the form of the server’s IP address (that is, 127.0.0.1) or its DNS entry (that is, aYVe# hZgkZg#Xdb).
EDGI
Optional. The port to which LDAP is configured for listening. The default is 389.
JH:GC6B:
Required if hZXjgZ attribute is set to 8;HHAT76H>8.
E6HHLDG9
Optional. The password used in conjunction with the JH:GC6B: attribute for authentication.
I>B:DJI
Optional. the time, in seconds, allowed for the LDAP operation before timeout occurs. If none is provided, the default is 60 seconds.
Using
KXYc\-*%) (continued) NAME
DESCRIPTION
B6MGDLH
Optional. Used only with 68I>DC2ºFjZgnº, this specifies the number of records to return from the LDAP query, similar to the 18;FJ:GN3 tag. Note that this attribute does not work with all LDAP servers.
HI6GI
Required (and only used) if 68I>DC2ºFjZgnº. This represents the DN starting point from which to begin the search within the Directory Information Tree (DIT).
H8DE:
Optional. Defines the scope for searching the DIT, starting at the value specified in the HI6GI attribute. Possible values are 7VhZ, DcZAZkZa, or HjWIgZZ.
6IIG>7JI:H
Required for FJ:GN, 699, BD9>;N, and BD9>;N9C actions. When used with FJ:GN, it represents a comma-delimited list of return values used as columns in a query output; an asterisk () returns all values. For 699 and BD9>;N, it represents a semicolon-separated list of add/modify values. For BD9>;N9C , it represents the new DN for the entry and does not check for correct syntax.
;>AI:G
Optional. Used with 68I>DC2ºFjZgnº to provide the search criteria for the query. The default filter is dW_ZXi8aVhh2, which returns all values.
HDGI
Optional. A comma-delimited list of attributes and sort directions by which to sort a query, as in HDGI2ºXc6H8!bV^a9:H8º.
HDGI8DCIGDA
Optional. A comma-delimited list of sort control options for a query. Possible values are VhX, YZhX, and cdXVhZ. Sorting, by default, is case-sensitive in ascending order (VhX). The YZhX value sorts the query in descending order, and cdXVhZ discards case-sensitivity. Values can be used in tandem, as in HDGI8DCIGDA2ºcdXVhZ!YZhXº.
9C
Required for 9:A:I:, 699, BD9>;N, and BD9>;N9C actions. Represents the DN for the entry being operated on.
HI6GIGDL
Optional. Used only with 68I>DC2ºFjZgnº, this specifies the starting row for returning records. The default is 1.
BD9>;NINE:
Optional. Used only with 68I>DC2ºBdY^[nº, this specifies the way to handle modifications within the attribute list. Possible values are VYY, gZeaVXZ, and YZaZiZ. Default value is ¹GZeaVXZº.
G:7>C9
Optional. Boolean value indicating whether 18;A96E3 should rebind the referral callback and reissue the query via the referred address using the original credentials. Default value is ¹cdº.
G:;:GG6A
Optional. Specifies the number of hops allowed in a referral. A zero value indicates 18;A96E3’s capability to use referred addresses is disabled, and no data is returned.
H:8JG:
Optional. Identifies the type of security to use, such as 8;HHAT76H>8 or 8;HHAT8A>:CIT6JI= , and additional information that is required by the corresponding security type. Possible field values are XZgi^ÄXViZTYW, XZgi^ÄXViZTcVbZ, `ZnTYW, and `ZnldgYTYW.
H:E6G6IDG
Optional. The character used to separate values in multivalue attributes. The default is a comma (!).
9:A>B>I:G
Optional. The character used to separate cVbZ2kVajZ pairs. The default is a semicolon (0).
G:IJGC6H7>C6GN
Optional. A comma- (or space) separated list of columns that are returned as a binary values.
369
370
CHAPTER
63
Interacting with Directory Services
EFK
DC2ºFJ:GNº C6B:2º\ZiHijYZcihº 6IIG>7JI:H2ºdj!Xc!bV^aº HI6GI2ºX2jhº H8DE:2ºHJ7IG::º ;>AI:G2ºdj2I^hX]HX]ddad[i]Z6gihº3 18;H8G>EI3 hi6iih2HigjXiCZl0 hi6iih#hZgkZg2¹aYVe#cnj#ZYjº0 hi6iih#VXi^dc2ºFJ:GNº0 hi6iih#Viig^WjiZh2ºdj!Xc!bV^aº0 hi6iih#cVbZ2º\ZiHijYZcih7n6iigº0 hi6iih#hiVgi2ºX2jhº0 hi6iih#hXdeZ2ºHJ7IG::º0 hi6iih#ÄaiZg2ºdj2I^hX]HX]ddad[i]Z6gihº0 1$8;H8G>EI3 18;A96E6GDC2ºhi6iihº$3
Because some of 18;A96E3’s attributes are a bit involved, the next few sections discuss in more depth how these attributes work.
K_\68I>DC8kki`Ylk\ ColdFusion’s 18;A96E3 tag supports five distinct actions: N
FJ:GN
N
699
N
BD9>;N
N
BD9>;N9C
N
9:A:I:
is the default. The FJ:GN action allows you to return a query object (record set) from an LDAP server. This can be used in the same way as any query object, such as one returned from the 18;FJ:GN3 tag. Three variables, in addition to the query results, are available to the returned query object: FJ:GN
N
GZXdgY8djci.
The number of records returned from the query object.
N
8dajbcA^hi.
N
8jggZciGdl. The current row index of the query being processed by an output mechanism, such as 18;DJIEJI3 or 18;ADDE3.
A comma-delimited list of column names in the query.
Using
When 68I>DC is set to FJ:GN, you are also required to use the C6B:, 6IIG>7JI:H, and HI6GI parameters. So at its simplest, your call to 18;A96E3 would look like this: 18;A96E 68I>DC2ºFJ:GNº C6B:2ºcVbZd[fjZgnº H:GK:G2ºhZgkZgadXVi^dcº 6IIG>7JI:H2ºViig^WjiZa^hiº HI6GI2ºhiVgi^c\adXVi^dc[dgi]ZfjZgnº3
The 699 action is used to add entries to your LDAP server. This action requires the 9C and 6IIG>7JI:H parameters. In this context, the DN is used to specify where to place the added entry in the DIT and should contain the full DN sequence. The 6IIG>7JI:H parameter is used to specify the cVbZ2kVajZ pairs to be added at the location specified in the 9C parameter. Each cVbZ2kVajZ pair should be delimited with a semicolon (0), unless otherwise specified in the 9:A>B>I:G parameter. The most basic form of an 699 action is as follows: 18;A96E 68I>DC2º699º H:GK:G2ºhZgkZgadXVi^dcº 6IIG>7JI:H2ºcVbZ2kVajZ0cVbZ'2kVajZ'0cVbZc2kVajZcº 9C2ºi]ZY^hi^c\j^h]ZYcVbZidVYYº3
The BD9>;N action allows you to modify attribute values for LDAP entries, one or more at a time. The only attribute that cannot be modified through this action is the DN, which is modified through the BD9>;N9C action. As with the 699 action, the BD9>;N action’s attributes are sent to the 6IIG>7JI:H parameter in semicolon-separated cVbZ2kVajZ pairs. The following is the BD9>;N action’s basic required format: 18;A96E 68I>DC2ºBD9>;Nº H:GK:G2ºhZgkZgadXVi^dcº 6IIG>7JI:H2ºcVbZ2kVajZ0cVbZ'2kVajZ'0cVbZc2kVajZcº 9C2ºi]ZY^hi^c\j^h]ZYcVbZd[i]ZZcignidWZbdY^ÄZYº3
The BD9>;N9C attribute performs one specific function: It changes the DN for an entry. To change the DN, you must supply the original DN as well as the new DN replacement: 18;A96E 68I>DC2ºBD9>;N9Cº H:GK:G2ºhZgkZgadXVi^dcº 6IIG>7JI:H2ºi]ZcZlgZeaVXZbZci9CkVajZº 9C2ºi]Zdg^\^cVa9CkVajZWZ^c\bdY^ÄZYº3
EFK
;N9CXkki`Ylk\f]18;A96E3[f\jefk Z_\Zbk_\;E]fijpekXo\iifij#Xe[XjXi\jlck#pfli\ekipdXpY\Zfd\dXc]fid\[%
The only requirement for deleting an entry is the entry’s DN. Having this value allows 18;A96E3 to locate the entity you want to delete. After you delete an entry, it is gone, and because of this, you should make sure that the DN value is correct.
371
372
CHAPTER
63
Interacting with Directory Services
To delete an entry, use the following syntax: 18;A96E 68I>DC2º9:A:I:º H:GK:G2ºhZgkZgadXVi^dcº 9C2ºi]Z9CgZegZhZci^c\i]ZZcignidYZaZiZº3
K_\H8DE:8kki`Ylk\ When querying an LDAP server, 18;A96E3 provides a means to narrow that search—in addition to filtering—with three types of “branch” scopes. Each of these scopes dictates how the search is performed relative to the value entered in the HI6GI attribute. In other words, the HI6GI attribute is used as a starting point for the search, and the H8DE: value tells 18;A96E3 where to search from that starting point. These scopes are as follows: If 76H: is chosen, 18;A96E3 only searches the current branch specified in the HI6GI attribute. Any branches above or below this branch are not searched.
N
76H:#
N
DC:A:K:A# To search a single level below the branch specified in the HI6GI attribute, use the DC:A:K:A value. This only searches one level below the starting branch. Any branches above or more than one level below this branch are not searched.
N
HJ7IG::#
This is the most commonly used value because it searches the entry specified in the HI6GI attribute as well as all branches beneath it. HjWIgZZ will not, however, search branches above the starting value. If you need to search branches higher up in the directory tree, simplify your starting value by making it more generalized.
Because of the recursive nature of the HjWIgZZ scope, performance may suffer with larger directory structures. As a result, you may want to use a drill-down approach when traversing a large directory, using the DC:A:K:A scope in succession.
K_\BD9>;NINE:8kki`Ylk\ When modifying an LDAP entry using 68I>DC2ºBdY^[nº, the BD9>;NINE: attribute allows you to specify which type of modification to perform. Having this capability allows you greater flexibility and control for modifying complex entries. The following list provides detailed descriptions for each BD9>;NINE: and the action(s) it performs: N
699# To add an attribute value to a multivalue entry, you can use the 699 modify type. The attribute(s) to be added should be listed in the 6IIG>7JI:H parameter as a semicolon-separated list, unless a different separator is specified in the H:E6G6IDG parameter.
N
9:A:I:#
N
G:EA68:# As the default modify type, the G:EA68: value overwrites the existing attribute(s) specified in the 6IIG>7JI:H parameter.
To delete a specific attribute from a multivalue entry, use the 9:A:I: modify type. The value listed in the 6IIG>7JI:H parameter represents the value to delete if it exists.
Interacting with Directories
EFK
;NXZk`fe%8[[`k`feXccp#\eki`\jk_XkZfekX`eCJAAmXcl\jZXeefkY\ df[`Ô\[%
K_\H:8JG:8kki`Ylk\ The H:8JG: attribute identifies which type of security to use in your LDAP calls. ColdFusion currently supports the 8;HHAT76H>8 only. The format for 8;HHAT76H>8 authentication takes two values: H:8JG:2¹8;HHAT76H>8!8:GI>;>86I:T97º
When using H:8JG:, keep the following in mind: N
The 8:GI>;>86I:T97 value is the name or path to a valid (Netscape cert7.db format) certificate database file. This value is the default and need not be explicitly specified.
N
The 8:GI>;>86I:TC6B: represents the client certificate to send to the server.
N
The @:NT97 value is the name or path to a valid (Netscape key3.db format) file that contains the public or private key pair for the certificate.
N
The @:NLDG9T97 holds the password to the key database (@:NT97).
N
If no path information is given for the 8:GI>;>86I:T97 or @:NT97 values, ColdFusion looks for them in the default LDAP directory.
@ek\iXZk`e^n`k_;`i\Zkfi`\j For the examples in this chapter, most LDAP servers will support the conventions used. You may, however, run into situations where certain attributes or object classes do not work, depending on the LDAP software you’re using. To understand more about the specific structure of your platform, check the documentation included with it.
8Zk`m\;`i\Zkfip Active Directory is an essential component of each version of Windows network architecture since Windows 2000. It behaves as a directory service to allow organizations to centrally manage information on users (including security information), as well as other network resources. Windows Domain Controllers each have an Active Directory service available, which provides access to the directory database. Using a standard CFLDAP tag, developers can integrate with this Active Directory to enable users to log into ColdFusion applications using their Windows network username and password. Listing 63.1 shows a simple example to authenticate users against Active Directory.
373
374
CHAPTER
63
Interacting with Directory Services
C`jk`e^-*%( aYVe6ji]#X[b —Authenticating a User with 18;A96E3 18;ADC3 18;>;CDI^h9ZÄcZY¹;dgb#jhZgcVbZº3 18;>C8AJ9:I:BEA6I:2ºad\^c$ad\^cT[dgb#X[bº3 18;67DGI3 18;:AH:3 18;IGN3 18;A96EVXi^dc2ºFJ:GNº C6B:2ºVji]º 6IIG>7JI:H2ºXcº HI6GI2ºXc2jhZgh!YX2iViVb!YX2cZiº H:GK:G2ºadXVa]dhiº EDGI2º(-.º JH:GC6B:2º[dgb#jhZgcVbZº E6HHLDG92º[dgb#eVhhldgYº3 18;H:I^h6ji]Zci^XViZY2ºnZhº3 18;86I8=ineZ2º6CNº3 18;H:I^h6ji]Zci^XViZY2ºcdº3 1$8;86I8=3 1$8;IGN3 18;>;kVg^VWaZh#^h6ji]Zci^XViZY3 18;ADCJH:G C6B:2º;dgb#jhZgcVbZº E6HHLDG92º;dgb#eVhhldgYº GDA:H2º6ji]Zci^XViZYJhZgº3 18;:AH:3 18;>C8AJ9:I:BEA6I:2ºad\^c$ad\^cT[dgb#X[bº3 1](3Ndjg^c[dgbVi^dc^hcdikVa^Y# EaZVhZignV\V^c#1$](3 18;67DGI3 1$8;>;3 1$8;>;3 1$8;ADC3
In Listing 63.1, an LDAP query is run against a Microsoft Active Directory (AD) and is wrapped with a 18;ADC3 tag. By specifying the username and password as provided by the end user’s form input, this query will run successfully only if those fields match a valid user’s username and password from the Active Directory. If either the username or password is incorrect, the Active Directory will throw an error message. By wrapping the call with a 18;IGN3 tag, we are able to catch the error message. The end result is that we have set a variable called ^h6ji]Zci^XViZY to either true if the query is able to run, or false if not. After the end of the 18;IGN3 block, we check the value of ^h6ji]Zci^XViZY. If it is true, the user is logged in; otherwise, the user is redirected to the login form.
Hl\ip`e^;`i\Zkfi`\j One of the first things you need to know about any action within 18;A96E3 that requires authentication is how to use the JH:GC6B: and E6HHLDG9 attributes. The first common mistake is to enter the username by itself, as odd as that may sound. Often the full DN is required for the entry that represents the user and the username: JH:GC6B:2ºXc2biViVb!Xc2GZX^e^Zcih!dj2DLH!d2DgVc\ZL]^eHijY^dhº
Interacting with Directories
Most of the time, however, you can just use the Xc as the username, like this: JH:GC6B:2ºXc2biViVbº
So in this example, the username is actually biViVb, but the JH:GC6B: attribute requires the Xc2 (common name) prefix. The E6HHLDG9 attribute, on the other hand, does not require any special considerations, so you simply enter it as it’s written: E6HHLDG92ºbiViVbT&'(º
EFK
DC2ºFJ:GNº C6B:2º7JI:H2ºº HI6GI2ºº ;>AI:G2ºj^Y2º3 1"""9^heaVnVaacVbZ$kVajZeV^gh[dgZVX]j^Y"""3 18;DJIEJIFJ:GN2º9I=2º&%%º7DG9:G2º&º8:AAHE68>C;8jggZciGdl:F&3 1IG31I=3CVbZ1$I=31I=3KVajZ1$I=31$IG3 1$8;>;3 1IG3 1I93cVbZ1$I931I93kVajZ1$I931$IG3 1$I67A:3 1$8;DJIEJI3
EFK
7JI:H value, you’re telling 18;A96E3 to return all attributes for all entries returned from the ;>AI:G scope value. In this example, you used the j^Y2 filter to signify that you want all entries () that have a j^Y returned. The dW_ZXi8aVhh is now dg\Vc^oVi^dcVaEZghdc!eZghdc!Ide
and one of the DNs is Xc2biViVb!Xc2GZX^e^Zcih!dj2DLH!d2DgVc\ZL]^eHijY^dh
Having this list of available attributes allows you to build your 699 action construct. In Listing 63.3, you’ll add “Ben Forta,” along with his corresponding personal information values, to the Orange Whip Studios (DLH) organizational unit (dj) within the company. C`jk`e^-*%* 6YY:cign#X[b —Adding and Testing an Entry 1"""JhZi]Z»699¼VXi^dcidXgZViZVcZlZcign"""3 18;A96E68I>DC2º699º H:GK:G2ºadXVa]dhiº JH:GC6B:2ºXc2biViVbº E6HHLDG92ºbiViVbT&'(º 6IIG>7JI:H2ºdW_ZXiXaVhh2dg\Vc^oVi^dcVaEZghdc!eZghdc!Ide0 Xc27Zc;dgiV0 hc2;dgiV0 bV^a27ZcT;dgiV5dgVc\Z"l]^e"hijY^dh#Xdb0 dj2DLHº 9C2ºXc2WZcT[dgiV!Xc2GZX^e^Zcih!dj2DLH!d2DgVc\ZL]^eHijY^dhº3 1"""FjZgnidZchjgZi]ZZcignlVhVYYZY"""3 18;A96E68I>DC2ºFJ:GNº C6B:2º7JI:H2ºYc!Xc!iZaZe]dcZcjbWZgº HI6GI2ºº ;>AI:G2ºj^Y2biViVbº3 1I67A:L>9I=2º&%%º7DG9:G2º&º8:AAHE68>CDC attribute set to BD9>;N. The first query returned a DN of Xc2biViVb!Xc2GZX^e^Zcih!dj2DLH!d2DgVc\ZL]^eHijY^dh
which is what you’ll use to modify the listing. For this next example, you’ll change the telephone number value. The first call to 18;A96E3, as shown previously in Listing 63.3, gathers the DN. This value is required for any modifications you want to make. The second call uses the first call’s DN as the value you supply to the DN attribute. Finally, one more 18;A96E3 call is used to requery the server, returning the newly modified results that contain the iZaZe]dcZCjbWZg value. See Listing 63.5 to get a better idea of how this works. C`jk`e^-*%, BdY^[nIZaZe]dcZ#X[b —Modifying an Entry 1"""JeYViZi]Z»iZaZe]dcZCjbWZg¼kVajZ"""3 1"""I]Z9CkVajZ^hjhZY[gdbVegZk^djh8;A96EXVaa"""3 18;A96E68I>DC2ºBD9>;Nº H:GK:G2ºadXVa]dhiº JH:GC6B:2ºXc2biViVbº E6HHLDG92ºbiViVbT&'(º 6IIG>7JI:H2ºiZaZe]dcZcjbWZg2.&.***"****º 9C2ºDC2ºFJ:GNº C6B:2º7JI:H2ºhi2C80higZZi2&'(DgVc\ZL]^eAVcZº BD9>;NINE:2º699º 9C2ºXc2biViVb!Xc2GZX^e^Zcih!dj2DLH!d2DgVc\ZL]^eHijY^dhº3 1"""GjcVfjZgnid\Vi]Zgi]ZcZlgZhjaih"""3 18;A96E68I>DC2ºFJ:GNº C6B:2º7JI:H2ºjc^fjZbZbWZgº HI6GI2ºXc2BVg`Zi^c\!Xc2GZX^e^Zcih!dj2DLH!d2DgVc\ZL]^eHijY^dhº3 1""">[i]Z\gdjeYdZhc¼iZm^hi!i]gdlVcZggdgbZhhV\ZVcYVWdgi"""3 18;>;CDI7JI:H2ºYcº HI6GI2ºº ;>AI:G2ºj^Y2JhZgº3 1"""8gZViZVhZb^Xdadc"hZeVgViZYa^hid[jhZg9C¼h"""3 1""":VX]9CcZZYhid]VkZ^ihXdbbVhZhXVeZYl^i]Vcdi]ZgXdbbV"""3 18;H:IBZbWZgh2BZbWZgh¹!ºGZeaVXZDC2ºBD9>;Nº H:GK:G2ºadXVa]dhiº JH:GC6B:2ºXc2biViVbº E6HHLDG92ºbiViVbT&'(º 6IIG>7JI:H2ºdW_ZXiXaVhh2\gdjeD[Jc^fjZCVbZh0jc^fjZbZbWZg2BZbWZghº 9C2ºXc2BVg`Zi^c\!Xc2GZX^e^Zcih!dj2DLH!d2DgVc\ZL]^eHijY^dhº3
While this is a tedious process, there is a far easier approach to making these modifications, with the use of the BdY^[nIneZ attribute. The final code for these sections can be found encapsulated in the A96E#X[X file shown in Listing 63.9 later in this chapter.
Df[`]p`e^;NINE: To help you appreciate the benefits of using the BD9>;NINE: attribute, the previous section demonstrated how cumbersome it can be to modify entries manually. Luckily, there is an easier way, by using the BD9>;NINE: attribute of the 18;A96E3 tag.
383
384
CHAPTER
63
Interacting with Directory Services
To recap, reread the section “The BD9>;NINE: Attribute” earlier in this chapter. The VYY modify type will look like the following: 18;A96E68I>DC2ºBD9>;Nº BD9>;NINE:2º699º H:GK:G2ºadXVa]dhiº JH:GC6B:2ºXc2biViVbº E6HHLDG92º_biViVbT&'(º 6IIG>7JI:H2ºXc2_d]cTYdZ!Xc2GZX^e^Zcih!dj2DLH!d2DgVc\ZL]^eHijY^dhº 9C2ºXc2BVg`Zi^c\!Xc2GZX^e^Zcih!dj2DLH!d2DgVc\ZL]^eHijY^dhº3
Had you added two users, you would separate each DN with a comma. To replace entries, use the gZeaVXZ modify type. :8LK@FE
9\ZXi\]lck_Xkpfl[fefkfm\ini`k\\o`jk`e^\eki`\jn`k_Xj`e^c\\ekip%K_\\eki`\jpfljlggcpkfk_\6IIG>7JI:HgXiXd\k\i n`cci\gcXZ\Xcc\o`jk`e^\eki`\j]fik_\;Ejg\Z`Ô\[%
For this example, you’ll replace the current marketing users with a list of the old users plus a new user, John Doe. For this example, all the new users are placed in a variable called BZbWZgh. Following is what the new users list will look like: Xc2biViVb!Xc2GZX^e^Zcih!dj2DLH!d2DgVc\ZL]^eHijY^dh! Xc2WZcT[dgiV!Xc2GZX^e^Zcih!dj2DLH!d2DgVc\ZL]^eHijY^dh! Xc2_d]cTYdZ!Xc2GZX^e^Zcih!dj2DLH!d2DgVc\ZL]^eHijY^dh
To replace the old members with the new, use the gZeaVXZ modify type: 18;A96E68I>DC2ºBD9>;Nº BD9>;NINE:2ºG:EA68:º H:GK:G2ºadXVa]dhiº JH:GC6B:2ºXc2biViVbº E6HHLDG92ºbiViVbT&'(º 6IIG>7JI:H2ºBZbWZghº 9C2ºXc2BVg`Zi^c\!Xc2GZX^e^Zcih!dj2DLH!d2DgVc\ZL]^eHijY^dhº3
To delete an entry, use the YZaZiZ modify type. This next example would delete the John Doe user from the Marketing group: 18;A96E68I>DC2ºBD9>;Nº BD9>;NINE:2º9:A:I:º H:GK:G2ºadXVa]dhiº JH:GC6B:2ºXc2biViVbº E6HHLDG92ºbiViVbT&'(º 6IIG>7JI:H2ºXc2_d]cTYdZ!Xc2GZX^e^Zcih!dj2DLH!d2DgVc\ZL]^eHijY^dhº 9C2ºXc2BVg`Zi^c\!Xc2GZX^e^Zcih!dj2DLH!d2DgVc\ZL]^eHijY^dhº3
Df[`]p`e^X;`jk`e^l`j_\[EXd\ Modifying a DN requires 18;A96E3’s BD9>;N9C action. You cannot modify a DN using the BD9>;N action.
Interacting with Directories
There are two values of interest when modifying a DN: the original DN and the replacement DN. The original DN is placed in the DN attribute, whereas the new replacement DN is placed in the 6IIG>7JI:H parameter as follows: 18;A96E68I>DC2ºBD9>;N9Cº H:GK:G2ºadXVa]dhiº JH:GC6B:2ºXc2biViVbº E6HHLDG92ºbiViVbT&'(º 6IIG>7JI:H2ºXc2_VcZTYdZ!Xc2GZX^e^Zcih!dj2DLH!d2DgVc\ZL]^eHijY^dhº 9C2ºXc2_d]cTYdZ!Xc2GZX^e^Zcih!dj2DLH!d2DgVc\ZL]^eHijY^dhº3
;\c\k`e^DC2º9:A:I:º H:GK:G2ºadXVa]dhiº JH:GC6B:2ºXc2biViVbº E6HHLDG92ºbiViVbT&'(º 9C2ºXc2biViVb!Xc2GZX^e^Zcih!dj2DLH!d2DgVc\ZL]^eHijY^dhº3
After the code is run, the entry is gone. As a safeguard, you may want to create a database to hold “deleted” entries in the event that you need to restore an accidentally deleted entry. Using this concept, you would query the entry to gather all its Name/Value pairs, run an insert query, and then, if all goes well, run the LDAP deletion. Listing 63.7 shows how to build a simple mailing list that enables you to send a message to every member in your LDAP directory. This example could be modified to filter specific groups or organizational units, or to enable you to specify filter options. The choices are unlimited. C`jk`e^-*%. A96EBV^aA^hi#X[b —Using LDAP to Create a Mailing List 1"""EgdXZhhXdYZ^[i]Z[dgblVhhjWb^iiZY"""3 18;>;>h9ZÄcZY¹;DGB#HjWb^iº3 1"""H^beaZ[dgbkVa^YVi^dc[dgZVX]ÄZaY"""3 18;>;CDIAZc;DGB#BZhhV\ZI^iaZ3 18;I=GDLB:HH6;3 18;>;CDIAZc;DGB#BZhhV\Z3 18;I=GDLB:HH6;3 1"""Gjci]ZA96EfjZgn"""3 18;A96E68I>DC2ºFJ:GNº C6B:2ºA96EBV^aA^hiº H:GK:G2ºadXVa]dhiº JH:GC6B:2ºXc2biViVbº E6HHLDG92ºbiViVbT&'(º H8DE:2ºHJ7IG::º
385
386
CHAPTER
63
Interacting with Directory Services
C`jk`e^-*%. (continued) 6IIG>7JI:H2ºXc!bV^aº HI6GI2ºº3 1""">[gZXdgYhVgZgZijgcZY!gjc8;B6>A"""3 18;>;A96EBV^aA^hi#GZXdgY8djci3 18;B6>A;GDB2ºa^hi"hZgkZ5dgVc\Z"l]^e"hijY^dh#Xdbº ID2ºbV^aº HJ7?:8I2º;dgb#BZhhV\ZI^iaZº H:GK:G2ºbV^a#dgVc\Z"l]^e"hijY^dh#Xdbº FJ:GN2ºA96EBV^aA^hiº3 =Zaad!Xc ;DGB#BZhhV\Z 1$8;B6>A3 1""";ZZYWVX`!hZci"""3 173NdjgbZhhV\ZlVhhjXXZhh[jaanhZci#1$731E3 18;:AH:3 1""";ZZYWVX`![V^aZY"""3 173CdgZXdgYhZm^hi^ci]ZY^gZXidgn#1$73 1$8;>;3 1$8;>;3 1""";dgbjhZYidZciZgi]ZbV^a^c\a^hiXdciZcih"""3 1;DGB68I>DC2ºA96EBV^aA^hi#X[bºB:I=D92ºedhiº3 :ciZgVi^iaZ[dgi]ZbV^a^c\/17G3 1>CEJIC6B:2ºBZhhV\ZI^iaZºB6MA:C7JI:H2ºº n_\ehl\ip`e^8Zk`m\;`i\Zkfip#@^\kk_\]fccfn`e^\iifi1 6cZggdg]VhdXXjggZYl]^aZign^c\idZmZXjiZfjZgn/PA96E/ZggdgXdYZ)"H^oZa^b^i :mXZZYZYR#
Fe\fidfi\f]k_\i\hl`i\[Xkki`Ylk\jXi\d`jj`e^fi`eZfii\Zk#fipfl[fefk_Xm\g\id`jj`fekf\o\Zlk\k_`jfg\iXk`fefek_\ j\im\i%
9l`c[`e^XeC;8G:=: Because we like to keep all data access logic in ColdFusion within CFCs, it makes sense to encapsulate all of our LDAP interactions into an LDAP CFC (see Listing 63.9). Each of the previous 18;A96E3 calls from this chapter were used to create this CFC.
387
388
CHAPTER
63
Interacting with Directory Services
C`jk`e^-*%0 A96E#X[X —Creating an LDAP CFC 18;8DBEDC:CI3 18;H8G>EI3 ^c^i0 1$8;H8G>EI3 18;;JC8I>DCC6B:2º^c^iº3 1"""HZZdca^cZa^hi^c\[dg[jaaXdYZ"""3 1$8;;JC8I>DC3 18;;JC8I>DCC6B:2º\ZiJhZghºG:IJGCINE:2ºfjZgnº688:HH2ºejWa^Xº3 1"""HZZdca^cZa^hi^c\[dg[jaaXdYZ"""3 1$8;;JC8I>DC3 18;;JC8I>DCC6B:2º\ZiJhZgh7nJ>9ºG:IJGCINE:2ºfjZgnº688:HH2ºeg^kViZº3 1"""8dYZhc^eeZid[[jcXi^dc#HZZdca^cZa^hi^c\[dg[jaaXdYZ"""3 18;A96E 68I>DC2ºFJ:GNº C6B:2º7JI:H2ºYc!Xc!bV^a!dW_ZXiXaVhhº HI6GI2ºViig^WjiZh#hiVgiº ;>AI:G2ºj^Y2Vg\jbZcih#ÄaiZgº3 1$8;;JC8I>DC3 18;;JC8I>DCC6B:2º\ZiJhZgh7n8CºG:IJGCINE:2ºfjZgnº688:HH2ºeg^kViZº3 1"""8dYZhc^eeZid[[jcXi^dc#HZZdca^cZa^hi^c\[dg[jaaXdYZ"""3 18;A96E 68I>DC2ºFJ:GNº C6B:2º7JI:H2ºYc!Xc!bV^a!dW_ZXiXaVhhº HI6GI2ºViig^WjiZh#hiVgiº ;>AI:G2ºXc2Vg\jbZcih#ÄaiZgº3 18;G:IJGC\Zi:bV^a3 1$8;;JC8I>DC3 18;;JC8I>DCC6B:2º\ZiCVbZKVajZEV^ghºG:IJGCINE:2ºfjZgnº3 1"""HZZdca^cZa^hi^c\[dg[jaaXdYZ"""3 1$8;;JC8I>DC3 18;;JC8I>DC C6B:2º\ZiCVbZKVajZEV^gh7nJ>9ºG:IJGCINE:2ºfjZgnº688:HH2ºeg^kViZº3 1"""8dYZhc^eeZid[[jcXi^dc#HZZdca^cZa^hi^c\[dg[jaaXdYZ"""3 18;A96E68I>DC2ºFJ:GNº C6B:2º7JI:H2ºº HI6GI2ºViig^WjiZh#hiVgiº ;>AI:G2ºj^Y2º3 1$8;;JC8I>DC3
Building an LDAP CFC
C`jk`e^-*%0 (continued) 18;;JC8I>DC C6B:2º\ZiCVbZKVajZEV^gh7n8CºG:IJGCINE:2ºfjZgnº688:HH2ºeg^kViZº3 1"""HZZdca^cZa^hi^c\[dg[jaaXdYZ"""3 18;A96E68I>DC2ºFJ:GNº C6B:2º7JI:H2ºº HI6GI2ºViig^WjiZh#hiVgiº ;>AI:G2ºXc2º3 1$8;;JC8I>DC3 18;;JC8I>DCC6B:2ºVYYJhZgºG:IJGCINE:2º7ddaZVcº3 1"""8dYZhc^eeZid[[jcXi^dc#HZZdca^cZa^hi^c\[dg[jaaXdYZ"""3 18;A96E68I>DC2º699º H:GK:G2ºhZgkZg6YYgº JH:GC6B:2ºXc2jhZgcVbZº E6HHLDG92ºeVhhldgYº 6IIG>7JI:H2ºdW_ZXiXaVhh2Vg\jbZcih#dW_ZXi8aVhh0 Xc2Vg\jbZcih#Xc0 hc2Vg\jbZcih#hc0 bV^a2Vg\jbZcih#ZbV^a0 dj2djº 9C2ºVg\jbZcih#Ycº3 1$8;;JC8I>DC3 18;;JC8I>DCC6B:2ºbdY^[nJhZgH^c\aZ;^ZaYºG:IJGCINE:2º7ddaZVcº3 1"""8dYZhc^eeZid[[jcXi^dc#HZZdca^cZa^hi^c\[dg[jaaXdYZ"""3 18;A96E68I>DC2ºBD9>;Nº BD9>;NINE:2ºVg\jbZcih#bdY^[nIneZº H:GK:G2ºhZgkZg6YYgº JH:GC6B:2ºXc2jhZgcVbZº E6HHLDG92ºeVhhldgYº 6IIG>7JI:H2ºVg\jbZcih#bdY^[n;^ZaY2Vg\jbZcih#bdY^[nKVajZº 9C2ºVg\jbZcih#9Cº3 1$8;;JC8I>DC3 18;;JC8I>DCC6B:2ºbdY^[nJhZgBjai^;^ZaYºG:IJGCINE:2º7ddaZVcº3 1"""8dYZhc^eeZid[[jcXi^dc#HZZdca^cZa^hi^c\[dg[jaaXdYZ"""3 18;A96E68I>DC2ºBD9>;Nº H:GK:G2ºhZgkZg6YYgº BD9>;NINE:2ºVg\jbZcih#bdY^[nIneZº JH:GC6B:2ºXc2jhZgcVbZº E6HHLDG92ºeVhhldgYº 6IIG>7JI:H2ºViig^WjiZHig^c\º 9C2ºVg\jbZcih#9Cº3 1"""8dYZhc^eeZid[[jcXi^dc#HZZdca^cZa^hi^c\[dg[jaaXdYZ"""3 1$8;;JC8I>DC3 18;;JC8I>DCC6B:2ºYZaZiZJhZgºG:IJGCINE:2º7ddaZVcº3 1"""8dYZhc^eeZid[[jcXi^dc#HZZdca^cZa^hi^c\[dg[jaaXdYZ"""3 18;A96E68I>DC2º9:A:I:º H:GK:G2ºhZgkZg6YYgº JH:GC6B:2ºXc2jhZgcVbZº E6HHLDG92ºeVhhldgYº 9C2ºViig^WjiZh#Ycº3 1$8;;JC8I>DC3 18;;JC8I>DCC6B:2ºbdY^[n9CºG:IJGCINE:2º7ddaZVcº3
389
390
CHAPTER
63
Interacting with Directory Services
C`jk`e^-*%0 (continued) 1"""8dYZhc^eeZid[[jcXi^dc#HZZdca^cZa^hi^c\[dg[jaaXdYZ"""3 18;A96E68I>DC2ºBD9>;N9Cº H:GK:G2ºhZgkZg6YYgº JH:GC6B:2ºXc2jhZgcVbZº E6HHLDG92ºeVhhldgYº 6IIG>7JI:H2ºViig^WjiZh#cZl9Cº 9C2ºViig^WjiZh#daY9Cº3 1$8;;JC8I>DC3 1$8;8DBEDC:CI3
All of the methods of this CFC directly mirror the code used throughout this chapter. One key difference is that the queries are split, built to either filter based on UID (used by most standard LDAP servers) or by CN, which is more likely to be used by Active Directory.
:?8GK9ºhZgkZg2ºhZhh^dc#hZgkZgº jhZgcVbZ2ºH:HH>DC#bV^aJhZgºeVhhldgY2ºH:HH>DC#bV^aEVhhlYº$3 1X[YjbekVg2ºXVaZcYVg>9º$3
K@G
KfZi\Xk\XeXggf`ekd\ek#lj\k_\XgZViZXZk`fen`k_flkjg\Z`]p`e^k_\GZfj^gZY6iiZcYZZhfiDei^dcVa 6iiZcYZZhXkki`Ylk\%
KXYc\-+%, Calendar Event Properties PROPERTY
DEFAULT
REQUIRED
DESCRIPTION
6aa9Vn:kZci
[VahZ
No, if :cYI^bZ is specified.
A Boolean value indicating whether this is an all-day event.
6iiVX]bZcih
No
One or more absolute paths to the files to send as attachments. Separate file paths with semicolons (;) on Windows, and colons (:) for Unix and Linux. Attachments are added to preexisting attachments when the bdY^[n action is used, and existing attachments are not deleted.
9jgVi^dc
No
The duration of the event in minutes.
:cYI^bZ
No, if 6aa9Vn:kZci The end time of the event, in any valid is true ColdFusion date-time format.
>bedgiVcXZ
cdgbVa
No
One of the following values: ]^\], cdgbVa, adl.
>hGZXjgg^c\
No
A Boolean value indicating whether this event repeats. If true, you must specify a GZXjggZcXZIneZ element and elements to specify the recurrence details. Table 64.6 lists the recurrence fields.
AdXVi^dc
No
A string that specifies the event location.
BZhhV\Z
No
A string containing a message describing the event. The string can include HTML formatting.
Dei^dcVa 6iiZcYZZh
No
A comma-delimited list of mail IDs.
Dg\Vc^oZg
No
A string that specifies the event organizer’s name.
GZb^cYZg
No
The time (in minutes) before the event, to display a reminder message.
397
398
CHAPTER
64
Integrating with Microsoft Exchange
KXYc\-+%, (continued) PROPERTY
DEFAULT
REQUIRED
DESCRIPTION
GZfj^gZY 6iiZcYZZh
No
A comma-delimited list of mail IDs.
GZhdjgXZh
No
A comma-delimited list of mail IDs for Exchange scheduling resources, such as conference rooms and display equipment.
HZch^i^k^in
No
One of the following values: cdgbVa, XdbeVcn"XdcÄYZci^Va, eZghdcVa, eg^kViZ.
HiVgiI^bZ
Yes
The start time of the event, in any valid ColdFusion date-time format. If you specify a date and time in this attribute and specify a N:6GAN GZXjggZcXZIneZ value with no other recurrence attributes, the event recurs yearly at the day and time specified in this attribute.
HjW_ZXi
No
A string that describes the event subject.
KXYc\-+%- Calendar Recurrence Types ELEMENT
TYPE
DEFAULT
DESCRIPTION
GZXjggZcXZIneZ
All
96>AN
Used only if the >hGZXjgg^c\ attribute is true. Must be one of the following values: 96>AN, L::@AN, BDCI=AN, N:6GAN.
igjZ
A Boolean value; if true, the event recurs until changed or deleted. Mutually exclusive with GZXjggZcXZ8djci and GZXjggZcXZ:cY9ViZ.
GZXjggZcXZCd:cY9ViZ All
GZXjggZcXZ8djci
All
The number of times the event recurs. Mutually exclusive with GZXjggZcXZ:cY9ViZ and GZXjggZcXZCd:cY9ViZ.
GZXjggZcXZ:cY9ViZ
All
The date of the last recurrence. Mutually exclusive with GZXjggZcXZ8djci and GZXjggZcXZCd:cY9ViZ.
GZXjggZcXZ;gZfjZcXn 96>AN, L::@AN, & BDCI=AN
The frequency of the recurrence in days, weeks, or months, depending on the type. For example, for 96>AN recurrence, a GZXjggZcXZ;gZfjZcXn value of ( schedules the event every three days.
GZXjg:kZgnLZZ`9Vn
The recurrence of the event on every weekday, but not on Saturday or Sunday. Mutually exclusive with GZXjggZcXZ;gZfjZcXn.
96>AN
ColdFusion Exchange Server Tags
KXYc\-+%- (continued) ELEMENT
TYPE
GZXjggZcXZ9Vnh
L::@AN
DEFAULT
DESCRIPTION
The day or days of the week on which the event occurs. Must be one or more of the following values in a comma-delimited list: BDC , IJ:, L:9, I=J, ;G>, H6I, HJC . If you omit this field for a weekly recurrence, the event recurs on the day of the week that corresponds to the specified start date.
GZXjggZcXZ9Vn
BDCI=AN, N:6GAN
The day of the week on which the event occurs. Must be one of the following values: BDC , IJ:, L:9, I=J, ;G>, H6I, HJC .
GZXjggZcXZLZZ`
BDCI=AN, N:6GAN
The week of the month or year on which the event recurs. Valid values are Äghi, hZXdcY, i]^gY, [djgi], aVhi.
GZXjggZcXZBdci]
N:6GAN
The month of the year on which the event recurs. Valid values are ?6C , ;:7, B6G, 6EG, B6N, ?JC , ?JA , 6J< , H:E, D8I, CDK, 9:8.
The YZaZiZ action removes existing events from the server. You must specify one or more event UIDs in a comma-delimited list. ColdFusion will ignore any invalid UIDs and delete only events specified with valid ones. It will throw an error if all the UIDs are invalid. The YZaZiZ6iiVX]bZcih action removes the specified existing attachment from the event on the server. You must specify a single event UID; multiple UIDs are not allowed. The \Zi action retrieves information about existing events. Use the cVbZ attribute to create a variable to contain the returned query. Use the 1X[ZmX]Vc\ZÄaiZg3 child tag to specify the event to retrieve. K@G
Lj\k_\\ZiXZk`fekfi\ki`\m\k_\L@;f]\m\ekjk_XkpflnXekkfXZZ\jjn`k_k_\YZaZiZ#YZaZiZ6iiVX]bZcih# \Zi6iig^WjiZh#bdY^[n#Xe[gZhedchZXZk`fej%
The \Zi6iiVX]bZcih action retrieves information about an existing event’s attachments. You must specify a single event UID; multiple UIDs are not allowed. Use the cVbZ attribute to create a variable to contain the returned query. EFK
C; directory of your ColdFusion 9 Enterprise multiserver or J2EE installation. In either case, you should find that the file already exists and has sample content that is inactive by virtue of being commented out, but if need be, you can simply create the file and the content. In both the X["lhge"edgiaZi#mba file and the edgiaZi#mba file, you define each portlet in the body of its own 1edgiaZi3 tag. You can create a single definition file that, with one important change, can be used as either your X["lhge"edgiaZi#mba file or your edgiaZi#mba file. This process works so well because both files conform to the Portlet 1.0 deployment descriptor format, and in those cases in which one file has slightly different requirements from the other, ColdFusion simply ignores information it doesn’t need—so the only issue is the one instance in which the same element needs a different value in the respective files. Listing 65.5 shows a sample of what this file could look like for deploying the CFCs from Listing 65.3 and Listing 65.4. C`jk`e^-,%, a^hi^c\+*T*#mba—ColdFusion 9 Portlet Definition File 14mbakZgh^dc2º%ºZcXdY^c\2ºJI;"-º43 1edgiaZi"Veembach2º]iie/$$_VkV#hjc#Xdb$mba$ch$edgiaZi$edgiaZi"VeeT&T%#mhYº mbach/mh^2º]iie/$$lll#l(#dg\$'%%&$MBAHX]ZbV"^chiVcXZº mh^/hX]ZbVAdXVi^dc2º]iie/$$_VkV#hjc#Xdb$mba$ch$edgiaZi$edgiaZi"VeeT&T%#mhY]iie/$$ _VkV#hjc#Xdb$mba$ch$edgiaZi$edgiaZi"VeeT&T%#mhYº kZgh^dc2º%º3 1edgiaZi3 1edgiaZi"cVbZ3Cdi]^c\EdgiaZi1$edgiaZi"cVbZ3 1Y^heaVn"cVbZmba/aVc\2ºZcº3Cdi]^c\EdgiaZi1$Y^heaVn"cVbZ3 1YZhXg^ei^dcmba/aVc\2ºZcº3I]^h^hVCdi]^c\EdgiaZi#1$YZhXg^ei^dc3 1edgiaZi"XaVhh3XdaY[jh^dc#edgiaZi#8daY;jh^dcEdgiaZi1$edgiaZi"XaVhh3 1^c^i"eVgVb3 1cVbZ3X[XCVbZ1$cVbZ3 1kVajZ3edgiaZih#a^hi^c\+*T(1$kVajZ3 1$^c^i"eVgVb3 1hjeedgiZY"adXVaZ3Zc1$hjeedgiZY"adXVaZ3
441
442
CHAPTER
65
Integrating with SharePoint and Portals
C`jk`e^-,%, (continued) 1hjeedgih3 1b^bZ"ineZ3iZmi$]iba1$b^bZ"ineZ3 1edgiaZi"bdYZ3K>:L1$edgiaZi"bdYZ3 1$hjeedgih3 1edgiaZi"^c[d3 1i^iaZ36Cdi]^c\EdgiaZi1$i^iaZ3 1$edgiaZi"^c[d3 1$edgiaZi3 1edgiaZi3 1edgiaZi"cVbZ3=ZaadLdgaYEdgiaZi1$edgiaZi"cVbZ3 1Y^heaVn"cVbZmba/aVc\2ºZcº3=ZaadLdgaYEdgiaZi1$Y^heaVn"cVbZ3 1YZhXg^ei^dcmba/aVc\2ºZcº3I]^h^hV=ZaadLdgaYEdgiaZi#1$YZhXg^ei^dc3 1edgiaZi"XaVhh3XdaY[jh^dc#edgiaZi#8daY;jh^dcEdgiaZi1$edgiaZi"XaVhh3 1^c^i"eVgVb3 1cVbZ3X[XCVbZ1$cVbZ3 1kVajZ3edgiaZih#a^hi^c\+*T)1$kVajZ3 1$^c^i"eVgVb3 1hjeedgiZY"adXVaZ3Zc1$hjeedgiZY"adXVaZ3 1hjeedgih3 1b^bZ"ineZ3iZmi$]iba1$b^bZ"ineZ3 1edgiaZi"bdYZ3K>:L1$edgiaZi"bdYZ3 1$hjeedgih3 1edgiaZi"^c[d3 1i^iaZ36=ZaadLdgaYEdgiaZi1$i^iaZ3 1$edgiaZi"^c[d3 1$edgiaZi3 1$edgiaZi"Vee3
You can see that the file has several elements for naming and describing each portlet. In addition, notice that for each portlet there are two elements for mapping that portlet to the CFC that implements that portlet’s functionality: the ci('PR
^ciPR
adc\$HnhiZb#>ci+)
adc\
adc\PR$HnhiZb#>ci+)PR
adc\PR
hWniZ$HnhiZb#HWniZ
WniZ
hWniZPR$HnhiZb#HWniZPR
WniZPR
h]dgi$HnhiZb#>ci&+
h]dgi
h]dgiPR$HnhiZb#>ci&+PR
h]dgiPR
HnhiZb#9ZX^bVa
W^\YZX^bVa
HnhiZb#Hig^c\
Hig^c\
EFK
ci&+
HnhiZb#7dmZYJH]dgi
j^ci$HnhiZb#J>ci('
HnhiZb#7dmZYJ>ci
jadc\$HnhiZb#J>ci+)
HnhiZb#7dmZYJAdc\
:fc[=lj`feXe[%Ec^i^Va^oZ8dbedcZci p r $$$1hjbbVgn3 $$$8aZVcjeVcngZhdjgXZhWZ^c\jhZY# $$$1$hjbbVgn3 egdiZXiZYdkZgg^YZkd^Y9^hedhZWddaY^hedh^c\ p ^[Y^hedh^c\XdbedcZcih2cjaa p XdbedcZcih#9^hedhZ0 r WVhZ#9^hedhZY^hedh^c\0 r ZcYgZ\^dc $$=ZaadLdgaYZmVbeaZlZWhZgk^XZ PLZWBZi]dYR ejWa^Xhig^c\=ZaadLdgaY p gZijgc¹=ZaadLdgaYº0 r r r
.NET Web Service: Returning a Simple Type
To compile the code in Visual Studio .NET, go to Build and select the proper build scenario. To build out all objects in the solution, select Build Solution or press Ctrl+Shift+B. Compile errors will be displayed in the output window. The message “Build: 1 succeeded, 0 failed, 0 skipped” means you’re ready to go and test your Web service. To do this, go to Debug and select Start. Internet Explorer will launch and display the LZWHZgk^XZ& class definition. The documentation provided through the .NET interface gives you the ability to test the =ZaadLdgaY method. Click it, and you’ll see the test page. Click Invoke, and a browser window is displayed showing the XML generated by the operation. Figure 66.4 shows the screens and the expected results. =`^li\--%+ WebService1 class definition and test page with result.
Notice that the default test scenario used here is exercised by an HTTP EDHI. This can prove problematic for applications that utilize an HTTP c^i^Va^oZ8dbedcZci p r $$$1hjbbVgn3 $$$8aZVcjeVcngZhdjgXZhWZ^c\jhZY# $$$1$hjbbVgn3 egdiZXiZYdkZgg^YZkd^Y9^hedhZWddaY^hedh^c\ p ^[Y^hedh^c\XdbedcZcih2cjaa p XdbedcZcih#9^hedhZ0 r WVhZ#9^hedhZY^hedh^c\0 r ZcYgZ\^dc $$I]Z:I>IA:!E>I8=I:MI!G6I>C9!HJBB6GN [gdbÄabh 1$8;FJ:GN3 18;H:I^ci6YYEVgV\gVe]8djcig26ggVnAZcMBA9dX#9dXjbZci#WdYn#e3 18;ADDEFJ:GN2ºfgn;^abGVi^c\hº3 18;H:I^ci6YYEVgV\gVe]8djcig2^ci6YYEVgV\gVe]8djcig &3 18;H:IiZbe26ggVn>chZgi6iMBA9dX#9dXjbZci#WdYn#MBA8]^aYgZc! ^ci6YYEVgV\gVe]8djcig! MBA:aZbCZlMBA9dX!¹l/eº3 1"""VYYVcZleVgV\gVe]VcYVcZlgdlidi]Z^chZgiZYeVgV\gVe]""""3 18;H:IiZbe26ggVn6eeZcYMBA9dX#9dXjbZci#WdYn#eP^ci6YYEVgV\gVe]8djcigR# MBA8]^aYgZc! MBA:aZbCZlMBA9dX!¹l/gº3 18;H:IiZbe26ggVn6eeZcYMBA9dX#9dXjbZci#WdYn#eP^ci6YYEVgV\gVe]8djcigR#g#MBA8]^aY gZc! MBA:aZbCZlMBA9dX!¹l/iº3 18;H:IMBA9dX#9dXjbZci#WdYn#eP^ci6YYEVgV\gVe]8djcigR#g#i#MBAIZmi2¹BDK>:I>IA:" E>I8=I:MIG6I>C9º3 1$8;ADDE3 18;H:IhigCZlMBA2idHig^c\MBA9dX3 18;;>A:68I>DC2¹lg^iZº ;>A:2º6eea^XVi^dc#LdgY#hig7aVc`IZbeaViZ9^gQldgYQYdXjbZci#mbaº DJIEJI2ºhigCZlMBAº3 18;O>E;>A:2º6eea^XVi^dc#LdgY#higDjieji9^gQXgZViZYdXmTJJ>9IZbe#YdXmº HIDG:E6I=2ºnZhº G:8JGH:2ºigjZº DK:GLG>I:2ºnZhº HDJG8:2º6eea^XVi^dc#LdgY#hig7aVc`IZbeaViZ9^gº$3 18;9JBEkVg2ºhigCZlMBAº3
You should be able to now open and start to use the new XgZViZYdXmTMMMM#YdXm file in Word 2007. Be careful; if you edit an OOXML document, it will add your edits in a different element. 1l/el/gh^YG2º%%;9''(+ºl/gh^YG9Z[Vjai2º%%;9''(+ºl/gh^YE2º%%;9''(+º3 1l/g3 1l/imba/heVXZ2ºegZhZgkZº36YYgZhh1$l/i3 1$l/g3 1$l/e3
Word OOXML Containers
The following XML is produced when the capital A was changed (revised) to a lowercase a: 1l/el/gh^YG2º%%;9''(+ºl/gh^YG9Z[Vjai2º%%;9''(+ºl/gh^YE2º%%;9''(+º3 1l/gl/gh^YG2º%%&+%)'6º3 1l/i3V1$l/i3 1$l/g3 1l/g3 1l/imba/heVXZ2ºegZhZgkZº3YYgZhh1$l/i3 1$l/g3 1$l/e3
Here,gh^YG is a revision identifier. It is a unique ID generated when an edit is made.
M`\n`e^XNfi[FFODC=`c\ Because of the revision identifier, the text can start to get lost within the SML. To view the raw text content of the YdXjbZci#mba file (without having document tracking, for instance), we can use the MBAHZVgX] function (Listing 67.4). C`jk`e^-.%+ K^Zl9D8#X[b —Viewing the Raw Text of a Word 2007 Document 1"""" ;^aZcVbZ/K^Zl9D8#X[b EjgedhZ/K^ZlVLdgY'%%,9D8ÄaZ 6ji]dg/BViiIViVb """"3 18;O>E68I>DC2ºGZVYº ;>A:2º6eea^XVi^dc#LdgY#higDjieji9^gQXgZViZYdXmT%-&6&.%;"(;;&");7%" **+.,(6,-6,;8:;-#YdXmº :CIGNE6I=2ºldgYQYdXjbZci#mbaº K6G>67A:2ºhigMBAiZmiº3 18;H:IMBA9dX2MBAEVghZ¹higMBAiZmiº3 18;H:ImbaEVgV\gVe]:aZbZcih2MbaHZVgX]MBA9dX!¹$$PadXVa"cVbZ2¼YdXjbZci¼R$PadXVa" cVbZ2¼WdYn¼R$PadXVa"cVbZ2¼e¼Rº3 18;H:ImbaEVgV\gVe]:aZbZcih2mbaEVgV\gVe]:aZbZcih3 18;ADDE;GDB2º&ºID2º6ggVnAZcmbaEVgV\gVe]:aZbZcihº>C9:M2º^ciEVgV8djcigº3 18;H:ImbaGdl:aZbZcih2MbaHZVgX]MBAEVghZmbaEVgV\gVe]:aZbZcihP^ciEVgV8djcigR! ¹$$PadXVa"cVbZ2¼e¼R$PadXVa"cVbZ2¼g¼R$PadXVa"cVbZ2¼i¼Rº3 18;ADDE;GDB2º&ºID2º6ggVnAZcmbaGdl:aZbZcihº>C9:M2º^ciGdl8djcigº3 18;DJIEJI3mbaGdl:aZbZcihP^ciGdl8djcigR#MBAIZmi1$8;DJIEJI3 1$8;ADDE3 17G3 1$8;ADDE3
:i\Xk`e^X;peXd`ZNfi[FFODC;fZld\ek You may be familiar with mail merging. In this example, we will create our own mail merge (dynamic) document by using a standard Word OOXML document. These are the basic steps: N
Open a document template.
N
Assign the part of the document to be dynamically populated,
N
Save the document.
475
476
CHAPTER
67
Integrating with Microsoft Office
EFK
E.
N
Read ldgYQYdXjbZci#mba.
N
Replace dynamic content with values.
N
Close, store, view, and deliver the document.
Changing the purchaser is simple. All we need to do is replace the characters with dynamic variables (Listing 67.5). C`jk`e^-.%, 9ncVb^X9D8#X[b —Replacing eaVXZ]daYZgh with Dynamic Content 1"""" ;^aZcVbZ/9ncVb^X9D8#X[b EjgedhZ/GZeaVXZi]ZeaVXZ]daYZghl^i]YncVb^XXdciZci[gdbVfjZgn# 6ji]dg/BViiIViVb """"3
Word OOXML Containers
C`jk`e^-.%, (continued) 18;H:I^ciXdciVXi>92(3 18;O>E68I>DC2ºjco^eº ;>A:2º6eea^XVi^dc#LdgY#higGddi9^gQ;^ab7jY\Zih#YdXmº 9:HI>C6I>DC2º6eea^XVi^dc#LdgY#higIZbe9^gQÄabWjY\ZiºdkZglg^iZ2ºnZhº3 18;;>A:68I>DC2¹gZVYº ;>A:2º6eea^XVi^dc#LdgY#higIZbe9^gQÄabWjY\ZiQldgYQYdXjbZci#mbaº K6G>67A:2ºhigMBAIZmiº3 18;FJ:GN96I6HDJG8:2¹DLHºC6B:2ºfgn8dciVXihº3 HZaZXi [gdbXdciVXihl]ZgZXdciVXi>92^ciXdciVXi>9 1$8;FJ:GN3 18;FJ:GN96I6HDJG8:2¹DLHºC6B:2ºfgn;^abhº3 HZaZXiBDK>:I>IA:!E>I8=I:MI!HJBB6GN!6BDJCI7J9C9 [gdbÄabh 1$8;FJ:GN3 18;DJIEJIFJ:GN2ºfgn8dciVXihº3 18;H:IhigMBAIZmi2gZeaVXZCd8VhZhigMBAIZmi!º;^ghiCVbZº!º;^ghiCVbZº!º6aaº3 18;H:IhigMBAIZmi2gZeaVXZCd8VhZhigMBAIZmi!ºAVhiCVbZº!ºAVhiCVbZº!º6aaº3 18;H:IhigMBAIZmi2gZeaVXZCd8VhZhigMBAIZmi!º6YYgZhhº!º6YYgZhhº!º6aaº3 18;H:IhigMBAIZmi2gZeaVXZCd8VhZhigMBAIZmi!ºX^inº!ºX^inº!º6aaº3 18;H:IhigMBAIZmi2gZeaVXZCd8VhZhigMBAIZmi!ºo^eº!ºo^eº!º6aaº3 18;H:IhigMBAIZmi2gZeaVXZCd8VhZhigMBAIZmi!ºXdjcignº!ºXdjcignº!º6aaº3 1$8;DJIEJI3 18;;>A:68I>DC2¹lg^iZº ;>A:2º6eea^XVi^dc#LdgY#higIZbe9^gQÄabWjY\ZiQldgYQYdXjbZci#mbaº DJIEJI2ºidHig^c\MBA9dXº3 18;O>E68I>DC2ºo^eº HIDG:E6I=2ºnZhº ;>A:2º6eea^XVi^dc#LdgY#higDjieji9^gQ;>ABWJ9chZgi6iMBA9dX#9dXjbZci#WdYn#iWa#MBA8]^aYgZc!>CI' ^ci8Zaa8djcig!MBAEVgi3 18;H:IMBA9dX#9dXjbZci#WdYn#iWa#igP^ci8Zaa8djcigR#iXP&R#eP&R#gP&R#iP&R#MBAIZmi2 ¹BDK>:I>IA:º3 18;H:IMBA9dX#9dXjbZci#WdYn#iWa#igP^ci8Zaa8djcigR#iXP'R#eP&R#gP&R#iP&R#MBAIZmi2 ¹E>I8=I:MIº3 18;H:IMBA9dX#9dXjbZci#WdYn#iWa#igP^ci8Zaa8djcigR#iXP(R#eP&R#gP&R#iP&R#MBAIZmi2 ¹HJBB6GNº3 18;H:IMBA9dX#9dXjbZci#WdYn#iWa#igP^ci8Zaa8djcigR#iXP)R#eP&R#gP&R#iP&R#MBAIZmi2AHXjgg ZcXn;dgbVi6BDJCI7J9C9º3 1$8;DJIEJI3 18;H:I^ci8Zaa8djcig2^ci8Zaa8djcig &3 18;H:IMBA9dX#9dXjbZci#WdYn#iWa#igP^ci8Zaa8djcigR#iXP)R#eP&R#gP&R#iP&R#MBAIZmi2 AHXjggZcXn;dgbViXjgIdiVa3 18;;>A:68I>DC2¹lg^iZº ;>A:2º6eea^XVi^dc#LdgY#higIZbe9^gQÄabWjY\ZiQldgYQYdXjbZci#mbaº DJIEJI2ºidHig^c\MBA9dXº3 18;O>E68I>DC2ºo^eº HIDG:E6I=2ºnZhº ;>A:2º6eea^XVi^dc#LdgY#higDjieji9^gQ;>ABWJ9DC2ºG:69º HG82¹;>A:E6I=º 8DAJBCH2¹G6CDC2ºlg^iZº ;>A:C6B:2ºhig;^aZCVbZº C6B:2ºmahh;^abhº H=::IC6B:2º;^abhº DK:GLG>I:2igjZ3
After you have run this script, you will be able to open the spreadsheet file in Excel and view the newly created workbook with the worksheet called Films (Figure 67.6). You have now created, populated, and written a spreadsheet. We are now on our way to rapidly developing a dynamic spreadsheet with multiple sheets. For demonstration purposes, we will save the file, and from now on we will read from the newly created spreadsheet file. =`^li\-.%The data that was populated by Listing 67.7.
EFK
EI3
Populating a Spreadsheet
C`jk`e^-.%/ (continued) hig;^aZCVbZ2DC2ºgZVYº HG82ºhig;^aZCVbZº H=::IC6B:2º;^abhº C6B:2ºmahh;^abhº$3 18;HEG:69H=::I 68I>DC2ºgZVYº HG82ºhig;^aZCVbZº H=::IC6B:2º;^abhº FJ:GN2ºfgn;^ab9ViVº$3 18;9JBEK6G2ºfgn;^ab9ViVº$3 18;9JBEK6G2ºmahh;^abhº$3
=`^li\-.%. The dump of the spreadsheet object and the query.
EFK
DC2ºGZVYº tag is then filtered for the desired information, as can be seen in Figure 67.8. The code then queries the database for film, expenses, directors, and actor data and uses the HegZVYh]ZZi6YYgdl function to individually populate the spreadsheet cells. C`jk`e^-.%0 EdejaViZHegZVYh]ZZi#X[b —Populating the Film Worksheet 1"""" ;^aZcVbZ/EdejaViZHegZVYh]ZZi#X[b EjgedhZ/EdejaViZVhegZVYh]ZZiÄaZ 6ji]dg/BViiIViVb """"3 18;E6G6BC6B:2ºjga#;^ab>9º9:;6JAI2º'º$3 1"""GZVYVcYedejaViZi]ZhegZVYh]ZZidW_ZXiVcYfjZgn[gdbi]Zldg`h]ZZiÄabh """3 18;H8G>EI3 hig;^aZCVbZ;gdb2GHIC6B:A6HIC6B:º$3 1$8;ADDE3 18;H8G>EI3 HegZVYh]ZZi6YY8dajbcmahh;^abh!¹hig8HK9^gZXidghº!^ciGDL8djci9^gZXidghHiVgi!'!; VahZ0 ^ciGDL8djci6XidghHiVgi2^ciGDL8djci9^gZXidghHiVgi fgn;^ab9^gZXidgh# GZXdgY8djci &0 HegZVYh]ZZi6YYgdlmahh;^abh!¹6Xidgh/º!^ciGDL8djci6XidghHiVgi!&!;VahZ0 hig8HK6Xidgh2¹º0 1$8;H8G>EI3
18;ADDEFJ:GN2ºfgn;^ab6Xidghº3 18;H:Ihig8HK6Xidgh2¹hig8HK6Xidgh!C6B:;>GHIC6B:A6HIº$3 1$8;ADDE3 18;H8G>EI3 HegZVYh]ZZi6YY8dajbcmahh;^abh!¹hig8HK6Xidghº!^ciGDL8djci6XidghHiVgi!'!;VahZ0 1$8;H8G>EI3 1""lg^iZi]Z;^abldg`h]ZZi^c[dgbVi^dc"""3 18;HEG:69H=::I 68I>DC2ºlg^iZº ;>A:C6B:2ºhig;^aZCVbZIdº C6B:2ºmahh;^abhº DK:GLG>I:2igjZ3
487
488
CHAPTER
67
Integrating with Microsoft Office
=`^li\-.%/ The Films worksheet.
The HegZVYh]ZZi6YY8dajbc function has the same parameters as the HegZVYh]ZZi6YYGdl function: HegZVYh]ZZi6YY8dajbcmahhDW_!higYViVP!^cihiVgi^c\gdl!^cihiVgiXdajbc!W^chZgiR
The first two parameters are a spreadsheet object and the data to populate the rows. This data is a comma-delimited list with each value representing a row. Again, the optional parameters for this function allow for us to specify the cell location to add the data and whether it will be an insert. In Listing 67.9, for demonstration purposes, we use a query to create a comma-delimited list of directors and actors and pass it as the higYViV parameter to the HegZVYh]ZZi6YY8dajbc function. We also determine the start rows for actors by evaluating how many directors there are and starting the actor information after the director section.
:i\Xk`e^Xe8[[`k`feXcJgi\X[j_\\k`eX Jgi\X[j_\\kFYa\Zk Most spreadsheet workbooks contain more than one spreadsheet. As previously discussed, this chapter’s listings create four worksheets within a spreadsheet document. To do this requires us to create a new worksheet using the HegZVYh]ZZi8gZViZH]ZZi function. The syntax is as follows: HegZVYh]ZZi8gZViZH]ZZimahhDW_!Phigh]ZZicVbZR
Although the sheet name is optional, I prefer to provide one (unless the functional specification states otherwise). After the new worksheet is created, we need to be able to define in a spreadsheet object what sheet we are manipulating. The functionHegZVYh]ZZiHZi6Xi^kZH]ZZimahhDW_! high]ZZicVbZ gives us the option to set the sheet as active, so any further calls to this spreadsheet object will manipulate the designated sheet.
Adding Formulas to Cells
The next worksheet we will create will list all expenses related to the specific film. The spreadsheet will also consist of the last cell (Amount column) that will display the sum of all expenses using a spreadsheet formula. The worksheet will look like Figure 67.9. Listing 67.10 adds a new sheet and then sets the active sheet to the newly created Expenses worksheet. After the sheet is set as active, the code populates and manipulates the active sheet’s data and formulas. =`^li\-.%0 The Expenses worksheet.
8[[`e^=fidlcXjkf:\ccj Most spreadsheets do not consist of just data. They also consist of cells that have formulas assigned to them. These formulas are one of the features that separate a spreadsheet from a simple CSV file. Among the new spreadsheet functions are the setter and getter for these cell formulas. The following is the syntax for both: HegZVYh]ZZiHZi8Zaa;dgbjaVmahhDW_!hig[dgbjaV!^cigdl!^ciXdajbc HegZVYh]ZZiEI3 hig;^aZCVbZ;gdb2:I>IA:!8DAT+higE>I8=I:MI!8DAT)^ci6BDJCI7J9C< ;GDBfgn;^ab9ViV L=:G:8DAT&2»jga#;^ab>9¼ 1$8;FJ:GN3 18;FJ:GN96I6HDJG8:2¹DLHºC6B:2ºfgn:meZchZhº3 HZaZXihjb:ME:CH:6BDJCI^ci:ME:CH:6BDJCI ;GDB:meZchZh L=:G:;^ab>92JGA#;^ab>9 1$8;FJ:GN3 18;FJ:GN96I6HDJG8:2¹DLHºC6B:2ºfgn;^ab9^gZXidghº3 H:A:8I9^gZXidgh# ;GDBÄabh >CC:G?D>C;^abh9^gZXidghDCÄabh#;>AB>92;^abh9^gZXidgh#;>AB>9 >CC:G?D>C9^gZXidghDC9^gZXidgh#9^gZXidg>92;^abh9^gZXidgh#9>G:8IDG>9 L=:G:;^abh#Äab>92JGA#;^ab>9 1$8;FJ:GN3 18;FJ:GN96I6HDJG8:2¹DLHºC6B:2ºfgn;^ab6Xidghº3 H:A:8I9>HI>C8I68IDGH#C6B:;>GHI!68IDGH#C6B:A6HI ;GDB;^abh >CC:G?D>C;^abh6XidghDCÄabh#;>AB>92;^abh#;^ab>9 >CC:G?D>C68IDGHDC;^abh6Xidgh#68IDG>926Xidgh#6Xidg>9 L=:G:;^abh#Äab>92JGA#;^ab>9 1$8;FJ:GN3
18;H8G>EI3 mahh;^abh2HegZVYh]ZZiCZl¹;^abhº!igjZ0 HegZVYh]ZZi6YYgdlmahh;^abh!¹CVbZ/!gZeaVXZfgnTfgn;^ab9ViV#higBDK>:I>IA:!¹!º!º ¹!ºVaaºº!&!&0 HegZVYh]ZZi6YYgdlmahh;^abh!¹HjbbVgn/!gZeaVXZfgnTfgn;^ab9ViV#higE>I8=I:MI! ¹!º!º¹!ºVaaºº!'!&0 $$HegZVYh]ZZi6YYgdlk^ZlhVXdbbV^ci]ZYViVVhVcZlXdajbc HegZVYh]ZZi6YYgdlmahh;^abh!¹7jY\Zi/!fgnTfgn;^ab9ViV#^ci6BDJCI7J9CEI3
18;ADDEFJ:GN2ºfgn;^ab6Xidghº3 18;H:Ihig8HK6Xidgh2¹hig8HK6Xidgh!C6B:;>GHIC6B:A6HIº$3 1$8;ADDE3 18;H8G>EI3 HegZVYh]ZZi6YY8dajbcmahh;^abh!¹hig8HK6Xidghº!^ciGDL8djci6XidghHiVgi!'!;VahZ0 1$8;H8G>EI3
1"""CZlLdg`h]ZZi¹:meZchZhº^ci]ZHegZVYh]ZZidW_ZXi"""3 18;FJ:GN96I6HDJG8:2¹DLHºC6B:2ºfgn;^ab:meZchZhº3 HZaZXi:ME:CH:96I:!9:H8G>EI>DC!:ME:CH:6BDJCI ;GDB:meZchZh L=:G:;^ab>92JGA#;^ab>9 1$8;FJ:GN3 1"""EgZeVgZi]Z:meZchZhh]ZZi"""3 18;H8G>EI3 HegZVYh]ZZi8gZViZH]ZZimahh;^abh!¹:meZchZhº0 HegZVYh]ZZiHZi6Xi^kZH]ZZimahh;^abh!¹:meZchZhº0 HegZVYh]ZZi6YYgdlmahh;^abh!¹9ViZ!9ZhXg^ei^dc!6bdjciº0 HegZVYh]ZZi6YYgdlhmahh;^abh!fgn;^ab:meZchZh!'!&0 ^ci:meZchZh8djci2fgn;^ab:meZchZh#GZXdgY8djci0 HegZVYh]ZZiHZi8Zaa;dgbjaVmahh;^abh!¹HJB8'/8º^ci^ci:meZchZh8djci &¹º! ^ci^ci:meZchZh8djci '!(0 1$8;H8G>EI3 18;FJ:GN96I6HDJG8:2¹DLHºC6B:2ºfgn;^abBZgX]VcY^hZº3 HZaZXiB:G8=C6B:!B:G8=9:H8G>EI>DC!B:G8=EG>8:!DG9:GFIN ;GDBBZgX]VcY^hZ A:;I?D>CBZgX]VcY^hZDgYZgh>iZbhDCBZgX]VcY^hZ#BZgX]>92BZgX]VcY^hZDgYZgh>iZbh# >iZb>9 A:;I?D>CBZgX]VcY^hZDgYZghDCBZgX]VcY^hZDgYZgh#DgYZg>92 BZgX]VcY^hZDgYZgh>iZbh#DgYZg>9 L=:G:;^ab>92JGA#;^ab>9 1$8;FJ:GN3 1""lg^iZi]Z;^abldg`h]ZZi^c[dgbVi^dc"""3 18;HEG:69H=::I 68I>DC2ºlg^iZº ;>A:C6B:2ºhig;^aZCVbZIdº C6B:2ºmahh;^abhº DK:GLG>I:2igjZ3
491
492
CHAPTER
67
Integrating with Microsoft Office
The worksheet, Merchandise, will have a number of formatted columns and a formula for the total. In addition, it will compute the quantity multiplied by the price to populate the Total column (Figure 67.10). As in previous examples, we will start by querying the database to create, populate, and format the desired columns in a spreadsheet object. Listing 67.11 demonstrates how to add and set as active a new sheet; it also shows one way of setting the row’s data and formula, using a query loop. =`^li\-.%(' The Merchandise worksheet.
C`jk`e^-.%(( 8gZViZ;dgbjaV#X[b —Setting a Cell’s Formula Within a Loop 1"""" ;^aZcVbZ/8gZViZ;dgbjaV#X[b EjgedhZ/9ZÄcZVhegZVYh]ZZi[dgbjaV 6ji]dg/BViiIViVb """"3 18;E6G6BC6B:2ºjga#;^ab>9º9:;6JAI2º'º$3 1"""GZVYVcYedejaViZi]ZhegZVYh]ZZidW_ZXiVcYfjZgn[gdbi]Zldg`h]ZZiÄabh """3 18;H8G>EI3 hig;^aZCVbZ;gdb2GHIC6B:A6HIC6B:º$3 1$8;ADDE3 18;H8G>EI3 HegZVYh]ZZi6YY8dajbcmahh;^abh!¹hig8HK9^gZXidghº!^ciGDL8djci9^gZXidghHiVgi!'!; VahZ0 ^ciGDL8djci6XidghHiVgi2^ciGDL8djci9^gZXidghHiVgi fgn;^ab9^gZXidgh# GZXdgY8djci &0 HegZVYh]ZZi6YYgdlmahh;^abh!¹6Xidgh/º!^ciGDL8djci6XidghHiVgi!&!;VahZ0 hig8HK6Xidgh2¹º0 1$8;H8G>EI3
18;ADDEFJ:GN2ºfgn;^ab6Xidghº3 18;H:Ihig8HK6Xidgh2¹hig8HK6Xidgh!C6B:;>GHIC6B:A6HIº$3 1$8;ADDE3 18;H8G>EI3 HegZVYh]ZZi6YY8dajbcmahh;^abh!¹hig8HK6Xidghº!^ciGDL8djci6XidghHiVgi!'!;VahZ0
493
494
CHAPTER
67
Integrating with Microsoft Office
C`jk`e^-.%(( (continued) 1$8;H8G>EI3
1"""CZlLdg`h]ZZi¹:meZchZhº^ci]ZHegZVYh]ZZidW_ZXi"""3 18;FJ:GN96I6HDJG8:2¹DLHºC6B:2ºfgn;^ab:meZchZhº3 HZaZXi:ME:CH:96I:!9:H8G>EI>DC!:ME:CH:6BDJCI ;GDB:meZchZh L=:G:;^ab>92JGA#;^ab>9 1$8;FJ:GN3 1"""EgZeVgZi]Z:meZchZhh]ZZi"""3 18;H8G>EI3 HegZVYh]ZZi8gZViZH]ZZimahh;^abh!¹:meZchZhº0 HegZVYh]ZZiHZi6Xi^kZH]ZZimahh;^abh!¹:meZchZhº0 HegZVYh]ZZi6YYgdlmahh;^abh!¹9ViZ!9ZhXg^ei^dc!6bdjciº0 HegZVYh]ZZi6YYgdlhmahh;^abh!fgn;^ab:meZchZh!'!&0 ^ci:meZchZh8djci2fgn;^ab:meZchZh#GZXdgY8djci0 HegZVYh]ZZiHZi8Zaa;dgbjaVmahh;^abh!¹HJB8'/8º^ci^ci:meZchZh8djci &¹º! ^ci^ci:meZchZh8djci '!(0 1$8;H8G>EI3 18;FJ:GN96I6HDJG8:2¹DLHºC6B:2ºfgn;^abBZgX]VcY^hZº3 HZaZXiB:G8=C6B:!B:G8=9:H8G>EI>DC!B:G8=EG>8:!DG9:GFIN ;GDBBZgX]VcY^hZ A:;I?D>CBZgX]VcY^hZDgYZgh>iZbhDCBZgX]VcY^hZ#BZgX]>92BZgX]VcY^hZDgYZgh>iZbh# >iZb>9 A:;I?D>CBZgX]VcY^hZDgYZghDCBZgX]VcY^hZDgYZgh#DgYZg>92 BZgX]VcY^hZDgYZgh>iZbh#DgYZg>9 L=:G:;^ab>92JGA#;^ab>9 1$8;FJ:GN3 1"""EgZeVgZi]ZBZgX]VcY^hZh]ZZi"""3 18;H8G>EI3 HegZVYh]ZZi8gZViZH]ZZimahh;^abh!¹BZgX]VcY^hZº0 HegZVYh]ZZiHZi6Xi^kZH]ZZimahh;^abh!¹BZgX]VcY^hZº0 ^ci8jggZciGdl2&0 HegZVYh]ZZi6YYgdlmahh;^abh!¹CVbZ!9ZhXg^ei^dc!Eg^XZ!FjVci^inHdaY!IdiVaº0 1$8;H8G>EI3 18;ADDEFJ:GN2ºfgn;^abBZgX]VcY^hZº3 18;H8G>EI3 ^ci8jggZciGdl2^ci8jggZciGdl &0 HegZVYh]ZZi6YYgdlmahh;^abh!¹gZeaVXZB:G8=C6B:!¹!º!º¹!ºVaaº!gZeaVXZB:G8 =9:H8G>EI>DC!¹!º!º¹!ºVaaº!B:G8=EG>8:!DG9:GFINº!^ci8jggZciGdl!&0 HegZVYh]ZZiHZi8Zaa;dgbjaVmahh;^abh!¹8º^ci8jggZciGdl¹9º ^ci8jggZciGdl¹º!^ci8jggZciGdl!*0 1$8;H8G>EI3 1$8;ADDE3
1""lg^iZi]Z;^abldg`h]ZZi^c[dgbVi^dc"""3 18;HEG:69H=::I 68I>DC2ºlg^iZº ;>A:C6B:2ºhig;^aZCVbZIdº C6B:2ºmahh;^abhº DK:GLG>I:2igjZ3
Adding Formatting to Cells
8[[`e^=fidXkk`e^kf:\ccj The Merchandise Order worksheet is similar to the Expenses worksheet with the date and currency format and a Total cell (which we will top with a double rule, as in Figure 67.11). Listing 67.12 shows how to format a particular cell. Some of the new functions for formatting a particular cell are as follows: HegZVYh]ZZi;dgbVi8Zaa, HegZVYh]ZZi;dgbVi8dajbc, HegZVYh]ZZi ;dgbVi8dajbch, HegZVYh]ZZi;dgbViGdl, HegZVYh]ZZi;dgbViGdlh# All of these functions require the spreadsheet object as well as a structure that represents a cell, row, or column format. Table 67.2 lists the name-value pairs that can optionally be specified. We must first create the format structure using [biIdiVa8dajbc2HigjXiCZl0
Then we will assign a name-value pair that formats the data: [biIdiVa8dajbc#YViV;dgbVi2¹!%#%%º0 [biIdiVa8dajbc#Ide7dgYZg2ºYdjWaZº0
Then we will apply the format to the specific cell: HegZVYh]ZZi;dgbVi8dajbchmahh;^abh![biIdiVa8dajbc!(0
After the spreadsheet has been manipulated, we need to the use the 8;HEG:69H=::I tag to write it to the file system. KXYc\-.%) The Format Struct Name and Value Pairs NAME
VALUES
Va^\cbZci
aZ[iYZ[Vjai!XZciZg!XZciZgThZaZXi^dc!Äaa!\ZcZgVa! _jhi^[n!g^\]i!kZgi^XVaTWdiidb!kZgi^XVaTXZciZg! kZgi^XVaT_jhi^[n!kZgi^XVaTide
WdaY
[VahZYZ[Vjai!igjZ
WdiidbWdgYZg
cdcZYZ[Vjai!YVh]ZY!YVh]TYdi!YVh]TYdiTYdi!YdiiZY! YdjWaZ!]V^g!bZY^jb!bZY^jbTYVh]TYdi!bZY^jbTYVh]TYdiT Ydi!bZY^jbTYVh]ZY!haVciZYTYVh]TYdi!i]^X`!i]^c
WdiidbWdgYZgXdadg
As per Xdadg values (dg\#VeVX]Z#ed^#]hh[#ji^a#=HH;8dadg)
Xdadg
As per Xdadg values (dg\#VeVX]Z#ed^#]hh[#ji^a#=HH;8dadg) VfjV!WaVX`!WajZ!WajZT\gZn!Wg^\]iT\gZZc!Wgdlc! XdgVa!XdgcÅdlZgTWajZ!YVg`TWajZ!YVg`T\gZZc!YVg`TgZY! YVg`TiZVa!YVg`TnZaadl!\daY!\gZZc!\gZnT'*TeZgXZci! \gZnT)%TeZgXZci!\gZnT*%TeZgXZci!\gZnT-%TeZgXZci!^cY^\d! aVkZcYZg!aZbdcTX]^[[dc!a^\]iTWajZ!a^\]iTXdgcÅdlZgTWajZ! a^\]iT\gZZc!a^\]iTdgVc\Z!a^\]iTijgfjd^hZ!a^\]iTnZaadl! a^bZ!bVgddc!da^kZT\gZZc!dgVc\Z!dgX]^Y!eVaZTWajZ! e^c`!eajb!gZY!gdhZ!gdnVaTWajZ!hZVT\gZZc!h`nTWajZ! iZVa!ijgfjd^hZ!k^daZi!l]^iZ!nZaadl
YViV[dgbVi
Most Excel formats are supported: , %#%%, Y"bbb"nn, and so on see CFML Reference for more)
[\Xdadg
As per Xdadg values (dg\#VeVX]Z#ed^#]hh[#ji^a#=HH;8dadg)
495
496
CHAPTER
67
Integrating with Microsoft Office
KXYc\-.%) (continued) NAME
VALUES
ÄaaeViiZgc
W^\ThedihYZ[Vjai!VaiTWVgh!Y^VbdcYh!ÄcZTYdih!aZVhiT Ydih!aZhhTYdih!cdÄaa!hda^YT[dgZ\gdjcY!heVghZTYdih! hfjVgZh!i]^X`TWVX`lVgYTY^V\!i]^X`T[dglVgYTY^V\!i]^X`T ]dgoTWVcYh!i]^X`TkZgiTWVcYh
[dci
Name of a font
[dcih^oZ
Size of the font (point size)
]^YYZc
[VahZ (default) or igjZ
^cYZci
Number of spaces to indent
^iVa^X
[VahZ (default) or igjZ
aZ[iWdgYZg
As per WdiidbWdgYZg values
aZ[iWdgYZgXdadg
As per Xdadg values
adX`ZY
[VahZ (default) or igjZ
g^\]iWdgYZg
As per WdiidbWdgYZg values
g^\]iWdgYZgXdadg
As per Xdadg values
gdiVi^dc
Integer representing the number of degrees in the range –90 to 90
hig^`Zdji
[VahZ (default) or igjZ
iZmilgVe
[VahZ (default) or igjZ
ideWdgYZg
As per WdiidbWdgYZg values
ideWdgYZgXdadg
As per Xdadg values
jcYZga^cZ
[VahZ (default) or igjZ
=`^li\-.%(( The Merchandise Order spreadsheet.
C`jk`e^-.%() ;dgbVi8Zaa#X[b —Formatting a Cell 1"""" ;^aZcVbZ/;dgbVi8Zaa#X[b EjgedhZ/;dgbViVhegZVYh]ZZiÄaZXZaa 6ji]dg/BViiIViVb """"3
Adding Formatting to Cells
C`jk`e^-.%() (continued) 18;E6G6BC6B:2ºjga#;^ab>9º9:;6JAI2º'º$3 1"""GZVYVcYedejaViZi]ZhegZVYh]ZZidW_ZXiVcYfjZgn[gdbi]Zldg`h]ZZiÄabh """3 18;H8G>EI3 hig;^aZCVbZ;gdb2IA:!8DAT+higE>I8=I:MI!8DAT)^ci6BDJCI7J9C< ;GDBfgn;^ab9ViV L=:G:8DAT&2»jga#;^ab>9¼ 1$8;FJ:GN3 18;FJ:GN96I6HDJG8:2¹DLHºC6B:2ºfgn:meZchZhº3 HZaZXihjb:ME:CH:6BDJCI^ci:ME:CH:6BDJCI ;GDB:meZchZh L=:G:;^ab>92JGA#;^ab>9 1$8;FJ:GN3 18;FJ:GN96I6HDJG8:2¹DLHºC6B:2ºfgn;^ab9^gZXidghº3 H:A:8I9^gZXidgh# ;GDBÄabh >CC:G?D>C;^abh9^gZXidghDCÄabh#;>AB>92;^abh9^gZXidgh#;>AB>9 >CC:G?D>C9^gZXidghDC9^gZXidgh#9^gZXidg>92;^abh9^gZXidgh#9>G:8IDG>9 L=:G:;^abh#Äab>92JGA#;^ab>9 1$8;FJ:GN3 18;FJ:GN96I6HDJG8:2¹DLHºC6B:2ºfgn;^ab6Xidghº3 H:A:8I9>HI>C8I68IDGH#C6B:;>GHI!68IDGH#C6B:A6HI ;GDB;^abh >CC:G?D>C;^abh6XidghDCÄabh#;>AB>92;^abh#;^ab>9 >CC:G?D>C68IDGHDC;^abh6Xidgh#68IDG>926Xidgh#6Xidg>9 L=:G:;^abh#Äab>92JGA#;^ab>9 1$8;FJ:GN3
18;H8G>EI3 mahh;^abh2HegZVYh]ZZiCZl¹;^abhº!igjZ0 HegZVYh]ZZi6YYgdlmahh;^abh!¹CVbZ/!gZeaVXZfgnTfgn;^ab9ViV#higBDK>:I>IA:!¹!º!º ¹!ºVaaºº!&!&0 HegZVYh]ZZi6YYgdlmahh;^abh!¹HjbbVgn/!gZeaVXZfgnTfgn;^ab9ViV#higE>I8=I:MI! ¹!º!º¹!ºVaaºº!'!&0 $$HegZVYh]ZZi6YYgdlk^ZlhVXdbbV^ci]ZYViVVhVcZlXdajbc
497
498
CHAPTER
67
Integrating with Microsoft Office
C`jk`e^-.%() (continued) HegZVYh]ZZi6YYgdlmahh;^abh!¹7jY\Zi/!fgnTfgn;^ab9ViV#^ci6BDJCI7J9CEI3 18;ADDEFJ:GN2ºfgn;^ab9^gZXidghº3 18;H:Ihig8HK9^gZXidgh2¹hig8HK9^gZXidgh!;>GHIC6B:A6HIC6B:º$3 1$8;ADDE3 18;H8G>EI3 HegZVYh]ZZi6YY8dajbcmahh;^abh!¹hig8HK9^gZXidghº!^ciGDL8djci9^gZXidghHiVgi!'!; VahZ0 ^ciGDL8djci6XidghHiVgi2^ciGDL8djci9^gZXidghHiVgi fgn;^ab9^gZXidgh# GZXdgY8djci &0 HegZVYh]ZZi6YYgdlmahh;^abh!¹6Xidgh/º!^ciGDL8djci6XidghHiVgi!&!;VahZ0 hig8HK6Xidgh2¹º0 1$8;H8G>EI3
18;ADDEFJ:GN2ºfgn;^ab6Xidghº3 18;H:Ihig8HK6Xidgh2¹hig8HK6Xidgh!C6B:;>GHIC6B:A6HIº$3 1$8;ADDE3 18;H8G>EI3 HegZVYh]ZZi6YY8dajbcmahh;^abh!¹hig8HK6Xidghº!^ciGDL8djci6XidghHiVgi!'!;VahZ0 1$8;H8G>EI3
1"""CZlLdg`h]ZZi¹:meZchZhº^ci]ZHegZVYh]ZZidW_ZXi"""3 18;FJ:GN96I6HDJG8:2¹DLHºC6B:2ºfgn;^ab:meZchZhº3 HZaZXi:ME:CH:96I:!9:H8G>EI>DC!:ME:CH:6BDJCI ;GDB:meZchZh L=:G:;^ab>92JGA#;^ab>9 1$8;FJ:GN3 1"""EgZeVgZi]Z:meZchZhh]ZZi"""3 18;H8G>EI3 HegZVYh]ZZi8gZViZH]ZZimahh;^abh!¹:meZchZhº0 HegZVYh]ZZiHZi6Xi^kZH]ZZimahh;^abh!¹:meZchZhº0 HegZVYh]ZZi6YYgdlmahh;^abh!¹9ViZ!9ZhXg^ei^dc!6bdjciº0 HegZVYh]ZZi6YYgdlhmahh;^abh!fgn;^ab:meZchZh!'!&0 ^ci:meZchZh8djci2fgn;^ab:meZchZh#GZXdgY8djci0 HegZVYh]ZZiHZi8Zaa;dgbjaVmahh;^abh!¹HJB8'/8º^ci^ci:meZchZh8djci &¹º! ^ci^ci:meZchZh8djci '!(0 1$8;H8G>EI3 18;FJ:GN96I6HDJG8:2¹DLHºC6B:2ºfgn;^abBZgX]VcY^hZº3 HZaZXiB:G8=C6B:!B:G8=9:H8G>EI>DC!B:G8=EG>8:!DG9:GFIN ;GDBBZgX]VcY^hZ A:;I?D>CBZgX]VcY^hZDgYZgh>iZbhDCBZgX]VcY^hZ#BZgX]>92BZgX]VcY^hZDgYZgh>iZbh# >iZb>9 A:;I?D>CBZgX]VcY^hZDgYZghDCBZgX]VcY^hZDgYZgh#DgYZg>92 BZgX]VcY^hZDgYZgh>iZbh#DgYZg>9 L=:G:;^ab>92JGA#;^ab>9
Adding Formatting to Cells
C`jk`e^-.%() (continued) 1$8;FJ:GN3 1"""EgZeVgZi]ZBZgX]VcY^hZh]ZZi"""3 18;H8G>EI3 HegZVYh]ZZi8gZViZH]ZZimahh;^abh!¹BZgX]VcY^hZº0 HegZVYh]ZZiHZi6Xi^kZH]ZZimahh;^abh!¹BZgX]VcY^hZº0 ^ci8jggZciGdl2&0 HegZVYh]ZZi6YYgdlmahh;^abh!¹CVbZ!9ZhXg^ei^dc!Eg^XZ!FjVci^inHdaY!IdiVaº0 1$8;H8G>EI3 18;ADDEFJ:GN2ºfgn;^abBZgX]VcY^hZº3 18;H8G>EI3 ^ci8jggZciGdl2^ci8jggZciGdl &0 HegZVYh]ZZi6YYgdlmahh;^abh!¹gZeaVXZB:G8=C6B:!¹!º!º¹!ºVaaº!gZeaVXZB:G8 =9:H8G>EI>DC!¹!º!º¹!ºVaaº!B:G8=EG>8:!DG9:GFINº!^ci8jggZciGdl!&0 HegZVYh]ZZiHZi8Zaa;dgbjaVmahh;^abh!¹8º^ci8jggZciGdl¹9º ^ci8jggZciGdl¹º!^ci8jggZciGdl!*0 1$8;H8G>EI3 1$8;ADDE3 18;FJ:GN96I6HDJG8:2¹DLHºC6B:2ºfgnBZgX]VcY^hZDgYZghº3 H:A:8I8dciVXih#;^ghiCVbZ!8dciVXih#AVhiCVbZ!hjbBZgX]VcY^hZDgYZgh>iZbh# DgYZgFinBZgX]VcY^hZDgYZgh>iZbh#>iZbEg^XZVhDgYZgIdiVa!BZgX]VcY^hZDgYZgh# H]^eHiViZ!BZgX]VcY^hZDgYZgh#H]^e8djcign!BZgX]VcY^hZDgYZgh#H]^eO^e! BZgX]VcY^hZDgYZgh#H]^e9ViZ ;GDB8dciVXih>CC:G?D>CBZgX]VcY^hZDgYZghDC8dciVXih#8dciVXi>92 BZgX]VcY^hZDgYZgh#8dciVXi>9 >CC:G?D>CBZgX]VcY^hZ >CC:G?D>CBZgX]VcY^hZDgYZgh>iZbhDCBZgX]VcY^hZ#BZgX]>92 BZgX]VcY^hZDgYZgh>iZbh#>iZb>9 DCBZgX]VcY^hZDgYZgh#DgYZg>92BZgX]VcY^hZDgYZgh>iZbh#DgYZg>9 EI3 HegZVYh]ZZi8gZViZH]ZZimahh;^abh!¹BZgX]VcY^hZDgYZghº0 HegZVYh]ZZiHZi6Xi^kZH]ZZimahh;^abh!¹BZgX]VcY^hZDgYZghº0 HegZVYh]ZZi6YYgdlmahh;^abh!¹;^ghiCVbZ!AVhiCVbZ!DgYZgIdiVa!HiViZ! 8djcign!O^e!H]^ee^c\9ViZº0 HegZVYh]ZZi6YYgdlhmahh;^abh!fgnBZgX]VcY^hZDgYZgh0 ^ciBZgX]VcY^hZDgYZgh8djci2fgnBZgX]VcY^hZDgYZgh#GZXdgY8djci0 HegZVYh]ZZiHZi8Zaa;dgbjaVmahh;^abh!¹HJB8'/8º^ci^ciBZgX]VcY^hZDgYZgh8djci &¹º!^ci^ciBZgX]VcY^hZDgYZgh8djci '!(0 $$;dgbVihi]ZDgYZgIdiVaXdajbcidcjbZg^X [biIdiVa8dajbc2HigjXiCZl0 [biIdiVa8dajbc#YViV;dgbVi2¹!%#%%º0 HegZVYh]ZZi;dgbVi8dajbchmahh;^abh![biIdiVa8dajbc!(0 $$;dgbVihi]ZH]^ee^c\YViVXdajbcid9ViZ [bi9ViZ8dajbc2HigjXiCZl0 [bi9ViZ8dajbc#YViV;dgbVi2¹Y"bbb"nnº0 HegZVYh]ZZi;dgbVi8dajbchmahh;^abh![bi9ViZ8dajbc!,0
499
500
CHAPTER
67
Integrating with Microsoft Office
C`jk`e^-.%() (continued) $$;dgbVihi]ZDgYZgIdiVaXdajbcidcjbZg^XVcY]VhVYdjWaZideWdgYZg [biIdiVa8dajbc2HigjXiCZl0 [biIdiVa8dajbc#YViV;dgbVi2¹!%#%%º0 [biIdiVa8dajbc#Ide7dgYZg2ºYdjWaZº0 HegZVYh]ZZi;dgbVi8Zaamahh;^abh![biIdiVa8dajbc!^ci^ciBZgX]VcY^hZDgYZgh8djci '! (0 1$8;H8G>EI3
1""lg^iZi]Z;^abldg`h]ZZi^c[dgbVi^dc"""3 18;HEG:69H=::I 68I>DC2ºlg^iZº ;>A:C6B:2ºhig;^aZCVbZIdº C6B:2ºmahh;^abhº DK:GLG>I:2igjZ3
8lkfdXk`fe Automation is the process of launching another application and controlling it programmatically through a public interface. All Office applications support automation and provide a COM interface that is accessible from ColdFusion. However, when an Office application is launched through automation, the resources and effect are the same as when the application is launched by a loggedin user. This behavior poses many problems for server-side integration, as with ColdFusion. The fact that there is no logged-in user can, in some circumstances, cause the Office application to lock up on launch, and lockups will occur at any point during use if an error message presents a modal dialog; the dialog will pop up and wait for a user to dismiss it. This behavior can pose a serious problem if someone isn’t sitting at the server constantly. The same is true if the application runs into a feature that isn’t installed and presents the Install on First Use dialog. Besides these serious problems, automation also presents concerns over scalability and security. The best recommendation regarding server-side automation of Microsoft Office applications comes directly from Microsoft: Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when run in this environment. ]iie/$$hjeedgi#b^Xgdhd[i#Xdb$YZ[Vjai#Vhem4hX^Y2`W0Zc"jh0'*,,*,
Microsoft makes this recommendation regarding its technology, but this recommendation applies equally to ColdFusion, Java, and all other server-side programming technologies.
:?8GKbV\Z"""3 1X[[jcXi^dccVbZ2º\Zi=^hid\gVb>bV\ZºVXXZhh2ºejWa^XºgZijgcineZ2ºVcnº djieji2º[VahZº]^ci2º>XgZViZVXdadg]^hid\gVbECbV\ZºgZfj^gZY2ºnZhºineZ2ºhig^c\º]^ci2º;^aZcVbZVcY eVi]d[^bV\ZidXgZViZ]^hid\gVbd[º$3 1X[Vg\jbZcicVbZ2ºl^Yi]ºgZfj^gZY2ºnZhºYZ[Vjai2º'*+ºineZ2ºcjbZg^Xº ]^ci2º]Z^\]id[ec\idXgZViZº$3 1X[Vg\jbZcicVbZ2º]Z^\]iºgZfj^gZY2ºnZhºYZ[Vjai2º&'%ºineZ2ºcjbZg^Xº ]^ci2º]Z^\]id[ec\idXgZViZº$3 1X[hXg^ei3 $$XgZViZXdadg]^hi\gVb kVg]^hid\gVb2\Zi=^hid\gVbVg\jbZcih#^ceji>bV\Z0 $$YgVlVcYgZijgc^bV\Z gZijgcYgVl=^hid\gVb]^hid\gVb!Vg\jbZcih#l^Yi]!Vg\jbZcih#]Z^\]i0 1$X[hXg^ei3 1$X[[jcXi^dc3 1"""222222222222222222222222222222222222222222222222222222222222222222222"""3 1"""\Zi8dadg=^hid\gVb>bV\Z"""3 1X[[jcXi^dccVbZ2º\Zi8dadg=^hid\gVb>bV\ZºVXXZhh2ºejWa^XºgZijgcineZ2ºVcnº djieji2º[VahZº]^ci2º>XgZViZVXdadg]^hid\gVbECbV\ZºgZfj^gZY2ºnZhºineZ2ºhig^c\º]^ci2º;^aZcVbZVcY eVi]d[^bV\ZidXgZViZ]^hid\gVbd[º$3 1X[Vg\jbZcicVbZ2ºl^Yi]ºgZfj^gZY2ºnZhºYZ[Vjai2º'*+ºineZ2ºcjbZg^Xº ]^ci2º]Z^\]id[ec\idXgZViZº$3 1X[Vg\jbZcicVbZ2º]Z^\]iºgZfj^gZY2ºnZhºYZ[Vjai2º&'%ºineZ2ºcjbZg^Xº ]^ci2º]Z^\]id[ec\idXgZViZº$3 1X[hXg^ei3 $$XgZViZXdadg]^hi\gVb kVg]^hid\gVb2\Zi8dadg=^hid\gVbVg\jbZcih#^ceji>bV\Z0
509
510
CHAPTER
68
Extending ColdFusion with Java
C`jk`e^-/%* (continued) $$YgVlVcYgZijgc^bV\Z gZijgcYgVl8dadg=^hid\gVb]^hid\gVb!Vg\jbZcih#l^Yi]!Vg\jbZcih#]Z^\]i0 1$X[hXg^ei3 1$X[[jcXi^dc3 1"""222222222222222222222222222222222222222222222222222222222222222222222"""3 1"""XgZViZ>ceji>bV\Z"""3 1X[[jcXi^dccVbZ2ºXgZViZ>ceji>bV\ZºVXXZhh2ºeg^kViZºgZijgcineZ2ºkd^Yº djieji2º[VahZº]^ci2º>XgZViZVc^bV\ZcZlº3 1X[Vg\jbZcicVbZ2º^ceji>bV\ZºgZfj^gZY2ºnZhºineZ2ºhig^c\ºYZ[Vjai2ºº ]^ci2º;^aZcVbZVcYeVi]d[^bV\ZidXgZViZ]^hid\gVbd[º$3 1X[hZikVg^VWaZh#^ceji>bV\Z2^bV\ZCZlVg\jbZcih#^ceji>bV\Z$3 1$X[[jcXi^dc3
1"""222222222222222222222222222222222222222222222222222222222222222222222"""3 1"""hZi7j[[ZgZY>bV\Z"""3 1X[[jcXi^dccVbZ2ºhZi7j[[ZgZY>bV\ZºVXXZhh2ºejWa^XºgZijgcineZ2ºkd^Yº djieji2º[VahZº]^ci2º>hZii]Zi]ZWj[[ZgZY^bV\Z!^XVcWZjhZY^[ndjlVciidhZi VWj[[ZgZY^bV\Z^chiZVYd[heZX^[n^c\V^bV\ZÄaZcVbZVcYeVi]º3 1X[Vg\jbZcicVbZ2ºWj[[ZgZY>bV\ZºgZfj^gZY2ºnZhº]^ci2º7j[[ZgZY^bV\Zº$3 1X[hZikVgeW2¹º$3 1X[hXg^ei3 eW2XgZViZDW_ZXi¹?VkVº!º_VkV#Vli#^bV\Z#gZcYZgVWaZ#EVgVbZiZg7adX`º#^c^i0 $$VYY^bV\ZhdjgXZ eW#VYYVg\jbZcih#Wj[[ZgZY>bV\Z0 $$XgZViZ?6>EaVcVg>bV\Z kVg^VWaZh#^ceji>bV\Z2kVg^VWaZh#?6>#XgZViZ¹6LI>bV\Zº!eW0 $$ kVg^VWaZh#^ceji>bV\Z>hEaVcVg>bV\Z2igjZ0 1$X[hXg^ei3 1$X[[jcXi^dc3 1"""222222222222222222222222222222222222222222222222222222222222222222222"""3 1"""XgZViZ?6>=^hid\gVb"""3 1X[[jcXi^dccVbZ2ºXgZViZ?6>=^hid\gVbºVXXZhh2ºeg^kViZºgZijgcineZ2ºhigjXiº djieji2º[VahZº]^ci2º>XgZViZV]^hid\gVbl^i]?6>º3 1X[hXg^ei3 kVgde2¹º0 kVgW^ch2¹º0 kVg^2%0 kVg]^hid\gVb2¹º0 kVgg\W2¹º0 $$XgZViZEVgVbZiZg7adX` kVgeW2XgZViZDW_ZXi¹?VkVº!º_VkV#Vli#^bV\Z#gZcYZgVWaZ#EVgVbZiZg7adX`º#^c^i0 $$XgZViZ]daYZghigjXijgZ kVg]^hid\gVbHigjXi2XgZViZ=^hid\gVb=daYZgHigjXi0 $$VYY^bV\ZhdjgXZ ^[^ceji>bV\Z>hEaVcVg>bV\Zp $$VagZVYnVeaVcVg^bV\Z eW#VYYHdjgXZkVg^VWaZh#^ceji>bV\Z0 rZahZp $$cZZYidXdckZgi eW#VYYHdjgXZ^bV\ZbV\ZkVg^VWaZh#^ceji>bV\Z0 r
Using Java Class Objects
C`jk`e^-/%* (continued) $$GZcYZgZYDe de2kVg^VWaZh#?6>#XgZViZ¹]^hid\gVbº!eW0 $$\Zi]^hid\gVb_VkVm#bZY^V#_V^#=^hid\gVb ]^hid\gVb2de#\ZiEgdeZgin¹]^hid\gVbº0 $$]^hid\gVbW^ch"VggVnP(RP'*+R W^ch2]^hid\gVb#\Zi7^ch0 $$VkZgV\ZXdadgh^cidh^c\aZVggVn [dg^2&0^AI:'*+0^2^ &p ]^hid\gVbHigjXi#]^hid\gVbP^R2GdjcYW^chP&RP^R W^chP'RP^R W^chP(RP^R$(0 r $$\ZihiVi^hi^Xh g\W2\Zi=^hid\gVbHiVi^hi^Xh]^hid\gVbHigjXi#]^hid\gVb0 ]^hid\gVbHigjXi#bZVc2g\W#bZVc0 ]^hid\gVbHigjXi#hiVcYVgYYZk^Vi^dc2g\W#hiVcYVgYYZk^Vi^dc0 ]^hid\gVbHigjXi#b^c2g\W#b^c0 ]^hid\gVbHigjXi#bVm2g\W#bVm0 $$gZijgc]^hid\gVbhigjXijgZ gZijgc]^hid\gVbHigjXi0 1$X[hXg^ei3 1$X[[jcXi^dc3 1"""222222222222222222222222222222222222222222222222222222222222222222222"""3 1"""XgZViZ?6>8dadg=^hid\gVb"""3 1X[[jcXi^dccVbZ2ºXgZViZ?6>8dadg=^hid\gVbºVXXZhh2ºeg^kViZºgZijgcineZ2ºhigjXiº djieji2º[VahZº]^ci2º>XgZViZVXdadg]^hid\gVbl^i]?6>º3 1X[hXg^ei3 kVgde2¹º0 kVgW^ch2¹º0 kVgbZVc6ggVn2¹º0 kVghY6ggVn2¹º0 $$XgZViZEVgVbZiZg7adX` kVgeW2XgZViZDW_ZXi¹?VkVº!º_VkV#Vli#^bV\Z#gZcYZgVWaZ#EVgVbZiZg7adX`º#^c^i0 $$XgZViZ]daYZghigjXi[dg]^hid\gVb kVgXdadg=^hid\gVb2higjXiCZl0 $$VYY^bV\ZhdjgXZ ^[^ceji>bV\Z>hEaVcVg>bV\Zp $$VagZVYnVeaVcVg^bV\Z eW#VYYHdjgXZkVg^VWaZh#^ceji>bV\Z0 rZahZp $$cZZYidXdckZgi eW#VYYHdjgXZ^bV\ZbV\ZkVg^VWaZh#^ceji>bV\Z0 r $$GZcYZgZYDe de2kVg^VWaZh#?6>#XgZViZ¹]^hid\gVbº!eW0 $$\Zi]^hid\gVb_VkVm#bZY^V#_V^#=^hid\gVb ]^hid\gVb2de#\ZiEgdeZgin¹]^hid\gVbº0 $$]^hid\gVbW^ch"VggVnP(RP'*+R W^ch2]^hid\gVb#\Zi7^ch0 bZVc6ggVn2]^hid\gVb#\ZiBZVc0 hY6ggVn2]^hid\gVb#\ZiHiVcYVgY9Zk^Vi^dc0 $$gZY Xdadg=^hid\gVb#g#]^hid\gVb2W^chP&R0 Xdadg=^hid\gVb#g#bZVc2bZVc6ggVnP&R0 Xdadg=^hid\gVb#g#hiVcYVgYYZk^Vi^dc2hY6ggVnP&R0 Xdadg=^hid\gVb#g#b^c2VggVnB^cW^chP&R0 Xdadg=^hid\gVb#g#bVm2VggVnBVmW^chP&R0
511
512
CHAPTER
68
Extending ColdFusion with Java
C`jk`e^-/%* (continued) $$\gZZc Xdadg=^hid\gVb#\#]^hid\gVb2W^chP'R0 Xdadg=^hid\gVb#\#]^hid\gVb2W^chP'R0 Xdadg=^hid\gVb#\#bZVc2bZVc6ggVnP'R0 Xdadg=^hid\gVb#\#hiVcYVgYYZk^Vi^dc2hY6ggVnP'R0 Xdadg=^hid\gVb#\#b^c2VggVnB^cW^chP'R0 Xdadg=^hid\gVb#\#bVm2VggVnBVmW^chP'R0 $$WajZ Xdadg=^hid\gVb#W#]^hid\gVb2W^chP(R0 Xdadg=^hid\gVb#W#]^hid\gVb2W^chP(R0 Xdadg=^hid\gVb#W#bZVc2bZVc6ggVnP(R0 Xdadg=^hid\gVb#W#hiVcYVgYYZk^Vi^dc2hY6ggVnP(R0 Xdadg=^hid\gVb#W#b^c2VggVnB^cW^chP(R0 Xdadg=^hid\gVb#W#bVm2VggVnBVmW^chP(R0 $$gZijgc]^hid\gVbhigjXijgZ gZijgcXdadg=^hid\gVb0 1$X[hXg^ei3 1$X[[jcXi^dc3 1"""222222222222222222222222222222222222222222222222222222222222222222222"""3 1"""YgVl=^hid\gVb"""3 1X[[jcXi^dccVbZ2ºYgVl=^hid\gVbºVXXZhh2ºeg^kViZºgZijgcineZ2ºVcnºdjieji2º[VahZº ]^ci2º>YgVlV]^hid\gVb^bV\Zº3 1X[Vg\jbZcicVbZ2º]^hid\gVbºgZfj^gZY2ºnZhº]^ci2º]^hid\gVbº$3 1X[Vg\jbZcicVbZ2ºl^Yi]ºgZfj^gZY2ºnZhºYZ[Vjai2º'*+ºineZ2ºcjbZg^Xº]^ci2ºl^Yi] d[^bV\ZidXgZViZº$3 1X[Vg\jbZcicVbZ2º]Z^\]iºgZfj^gZY2ºnZhºYZ[Vjai2º&'%ºineZ2ºcjbZg^Xº ]^ci2º]Z^\]id[^bV\ZidXgZViZº$3 1X[hXg^ei3 kVg^^2¹º0 $$XgZViZ^bV\Z kVg]^hi>bV\Z2^bV\ZCZl¹º!'*+!Vg\jbZcih#]Z^\]i!ºVg\Wº0 $$hZiYgVl^c\Xdadg >bV\ZHZi9gVl^c\8dadg]^hi>bV\Z!ºWaVX`º0 $$addei]gjVaaW^ch^cXdadg [dg^^2&0^^AI:'*+0^^2^^ &p $$hZibVm]Z^\]iWVhZYdci]ZbVmh^oZ[djcY^cVggVn a^cZ=Z^\]i2Vg\jbZcih#]Z^\]i"Vg\jbZcih#]^hid\gVb#]^hid\gVbP^^R$ VggVnBVmVg\jbZcih#]^hid\gVb#]^hid\gVbVg\jbZcih#]Z^\]i0 $$YgVla^cZ ^bV\Z9gVlA^cZ]^hi>bV\Z!^^"&!Vg\jbZcih#]Z^\]i!^^"&!a^cZ=Z^\]i0 r $$gZh^oZl^Yi]^[cZZYZY ^[Vg\jbZcih#l^Yi]2'*+p >bV\ZHZi6ci^Va^Vh^c\]^hi>bV\Z!ºdcº0 >bV\ZGZh^oZ]^hi>bV\Z!Vg\jbZcih#l^Yi]!Vg\jbZcih#]Z^\]i!º]^\]ZhiFjVa^inº0 r0 $$gZijgc^bV\Z gZijgc]^hi>bV\Z0 1$X[hXg^ei3 1$X[[jcXi^dc3 1"""222222222222222222222222222222222222222222222222222222222222222222222"""3 1"""YgVl8dadg=^hid\gVb"""3 1X[[jcXi^dccVbZ2ºYgVl8dadg=^hid\gVbºVXXZhh2ºeg^kViZºgZijgcineZ2ºVcnº djieji2º[VahZº]^ci2º>YgVlVXdadg]^hid\gVb^bV\Zº3 1X[Vg\jbZcicVbZ2º]^hid\gVbºgZfj^gZY2ºnZhº]^ci2º]^hid\gVbº$3
Using Java Class Objects
C`jk`e^-/%* (continued) 1X[Vg\jbZcicVbZ2ºl^Yi]ºgZfj^gZY2ºnZhºYZ[Vjai2º'*+ºineZ2ºcjbZg^Xº]^ci2ºl^Yi] d[^bV\ZidXgZViZº$3 1X[Vg\jbZcicVbZ2º]Z^\]iºgZfj^gZY2ºnZhºYZ[Vjai2º&'%ºineZ2ºcjbZg^Xº ]^ci2º]Z^\]id[^bV\ZidXgZViZº$3 1X[hXg^ei3 kVg^2¹º0 kVg^^2¹º0 kVgXdadg2¹º0 $$XgZViZ^bV\Z kVg]^hi>bV\Z2^bV\ZCZl¹º!'*+!Vg\jbZcih#]Z^\]i!ºVg\Wº0 $$hZiYgVl^c\igVcheVgZXZcn >bV\ZHZi9gVl^c\IgVcheVgZcXn]^hi>bV\Z!++0 $$addei]gjXdadgW^chg"\"W [dg^2&0^AI:(0^2^ &p $$hZiXdadgWVhZYdcW^c ^[^22&p$$gZY >bV\ZHZi9gVl^c\8dadg]^hi>bV\Z!ºgZYº0 Xdadg2¹gº0 rZahZ^[^22'p$$\gZZc >bV\ZHZi9gVl^c\8dadg]^hi>bV\Z!º\gZZcº0 Xdadg2¹\º0 rZahZ^[^22(p$$WajZ >bV\ZHZi9gVl^c\8dadg]^hi>bV\Z!ºWajZº0 Xdadg2¹Wº0 r $$addei]gjVaaW^ch^cXdadg [dg^^2&0^^AI:'*+0^^2^^ &p $$hZibVm]Z^\]iWVhZYdci]ZbVmh^oZ[djcY^cVggVn a^cZ=Z^\]i2Vg\jbZcih#]Z^\]i"Vg\jbZcih#]^hid\gVbPXdadgR#]^hid\gVbP^^R$ VggVnBVmVg\jbZcih#]^hid\gVbPXdadgR#]^hid\gVbVg\jbZcih#]Z^\]i0 $$YgVla^cZ ^bV\Z9gVlA^cZ]^hi>bV\Z!^^"&!Vg\jbZcih#]Z^\]i!^^"&!a^cZ=Z^\]i0 r r $$gZh^oZl^Yi]^[cZZYZY ^[Vg\jbZcih#l^Yi]2'*+p >bV\ZHZi6ci^Va^Vh^c\]^hi>bV\Z!ºdcº0 >bV\ZGZh^oZ]^hi>bV\Z!Vg\jbZcih#l^Yi]!Vg\jbZcih#]Z^\]i!º]^\]ZhiFjVa^inº0 r0 $$gZijgc^bV\Z gZijgc]^hi>bV\Z0 1$X[hXg^ei3 1$X[[jcXi^dc3 1"""222222222222222222222222222222222222222222222222222222222222222222222"""3 1"""XgZViZ=^hid\gVb=daYZgHigjXi"""3 1X[[jcXi^dccVbZ2ºXgZViZ=^hid\gVb=daYZgHigjXiºVXXZhh2ºeg^kViZº gZijgcineZ2ºhigjXiºdjieji2º[VahZº]^ci2º>XgZViZV]^hid\gVbVggVnº3 1X[hXg^ei3 kVg]daYZgHigjXi2higjXiCZl0 ]daYZgHigjXi#]^hid\gVb2VggVnCZl&0 ]daYZgHigjXi#bZVc2¹º0 ]daYZgHigjXi#hiVcYVgYYZk^Vi^dc2¹º0 ]daYZgHigjXi#b^c2¹º0 ]daYZgHigjXi#bVm2¹º0 gZijgc]daYZgHigjXi0 1$X[hXg^ei3
513
514
CHAPTER
68
Extending ColdFusion with Java
C`jk`e^-/%* (continued) 1$X[[jcXi^dc3 1"""222222222222222222222222222222222222222222222222222222222222222222222"""3 1"""\Zi=^hid\gVbHiVi^hi^Xh"""3 1X[[jcXi^dccVbZ2º\Zi=^hid\gVbHiVi^hi^XhºVXXZhh2ºeg^kViZºdjieji2º[VahZº3 1X[Vg\jbZcicVbZ2ºkVajZhºgZfj^gZY2ºnZhº3 1X[hXg^ei3 kVggZijgcHigjXi2higjXiCZl0 $$kVg]^hi6ggVn2Vg\jbZcih#kVajZh0 kVgCjbKVajZh2%0 kVgm2%0 kVghjbm2%0 kVg^2%0 $$b^c gZijgcHigjXi#b^c2VggVnB^cVg\jbZcih#kVajZh0 $$bVm gZijgcHigjXi#bVm2VggVnBVmVg\jbZcih#kVajZh0 ]^hiAZc\i]2VggVnAZcVg\jbZcih#kVajZh0 m2VggVn6k\Vg\jbZcih#kVajZh0 [dg^2&0^AI:]^hiAZc\i]0^2^ &p hjbm2hjbm Vg\jbZcih#kVajZhP^R"mVg\jbZcih#kVajZhP^R"m0 r0 $$bZVc gZijgcHigjXi#bZVc2m0 $$H9 gZijgcHigjXi#hiVcYVgYYZk^Vi^dc2hfghjbm$]^hiAZc\i]0 gZijgcgZijgcHigjXi0 1$X[hXg^ei3 1$X[[jcXi^dc3 1$X[XdbedcZci3
We will not go into depth about how this CFC works because we are assuming that you are familiar enough with Java to look up each class and method requested from the JAI library. One thing to note is how cleanly ColdFusion allows you to integrate with Java components and libraries using either standard CFML or CFScript. Now let us use 8;>B6C;$a^W$iV\a^W#_Vgº, replacing the iV\a^W part with the actual file names in question.
EG:;>M
A prefix to use for referring to the tags in the tag library. For the remainder of the current ColdFusion page, you will be able to refer to the tags in the form 1egZÄm/iV\cVbZ3, where the egZÄm is the value you supply here.
K@G
PflZXegifm`[\Xep`[\ek`Ô\ipflnXekXjk_\EG:;>M#Xjcfe^Xj`k`jefkXi\j\im\[nfi[#Ylkk_\i\n`ccljlXccpY\XZljkfdXip gi\Ôo]fik_\kX^c`YiXippflËi\lj`e^f]k\ek_\jXd\gi\Ôolj\[`ek_\[fZld\ekXk`fefi\oXdgc\jk_XkZfd\n`k_k_\c`YiXip %@ i\Zfdd\e[k_Xkpfllj\k_\ZljkfdXipgi\Ôon_\e\m\igfjj`Yc\% EFK
cXajYZV?HEeV\Z"""3 1X[hZiciZ\gVi^c\?HE#_heº3
Integrating with Java Servlets and JSP Pages
C`jk`e^-/%/ (continued) 1"""6cdi]Zg8daY;jh^dcbZhhV\Z"""3 1X[djieji3 1e31W3Jb!]^!i]^h^h8daY;jh^dcV\V^c#1$W31Wg3 L]Vi]VeeZcZY!Y^Y9g#?HE[dg\Zil]Vih]ZlVh\d^c\idhVnV\V^c4 I]dhZ?HEhiZcYidÅV`Zdji[gdbi^bZidi^bZ# >¼aaeVhhndjdkZgid>ciZ\gVi^c\HZgkaZicdl# 6ldgYd[lVgc^c\/]Z¼hVW^i###higZhhZYdjiaViZan# >]deZndjbV`Z^iWVX`^cdcZe^ZXZ###1Wg3 1$X[djieji3 1""">cXajYZV?VkVHZgkaZi"""3 1X[hZiciZ\gVi^c\HZgkaZiº3 1"""H]dli]ViG:FJ:HIkVg^VWaZXVcWZX]Vc\ZYWn?HEeV\ZhdgHZgkaZih"""3 1X[djieji3 1e31W3=^!i]^h^h8daY;jh^dcdcXZV\V^c#1$W31Wg3 LZaa!^i¼hhjgZWZZcc^XZiVa`^c\idndj!G:FJ:HI#CVbZ#1Wg3 =VkZVc^XZV[iZgcddc1Wg3 1$X[djieji3 1$WdYn3 1$]iba3
Listing 68.9 shows the code for the JSP page that is included by the ColdFusion page in Listing 68.8. Note that it is able to use standard JSP-style gZfjZhi#\Zi6iig^WjiZ syntax to refer to the value that ColdFusion calls G:FJ:HI#CVbZ. C`jk`e^-/%0 >ciZ\gVi^c\?HE#_he —JSP Page Included by Listing 68.8 1"" ;^aZcVbZ/>ciZ\gVi^c\?HE#_he 6ji]dg/CViZLZ^hhCBL EjgedhZ/9ZbdchigViZhkVg^VWaZ"h]Vg^c\WZilZZcZck^gdcbZcih ""3
1""I]ZG:FJ:HIkVg^VWaZi]VilVhhZi^ci]Z8daY;jh^dceV\Z""3 1""^hVkV^aVWaZ]ZgZVhVcViig^WjiZd[i]Z?HE¹gZfjZhiºdW_ZXi""3 1e3 1W3=^i]ZgZ12gZfjZhi#\Zi6iig^WjiZ¹cVbZº3# 9g#?HE]ZgZ###]dlnVYd^c\41$W31Wg3 XdbeaZiZan[dg\dil]Vi>lVh\d^c\idhVn#1Wg3 >¼¼b\d^c\ideVhhndjWVX`id8daY;jh^dccdl#EZVXZdji!YjYZ1Wg3
EFK
Xk\nXp@ejkXeZ\ Inside the ColdFusion Administrator you will need to go to the Event Gateway Instances properties page and add a new gateway instance. For this application, we called our gateway =ZaeYZh`, we called our gateway CFC ^b#X[X, and we called our configuration file ]ZaeYZh`#X[\. There are two key details in creating your new instance: the CFC that will handle all of your requests and the configuration file itself. Make sure you get these both right and you will be set. K@G
8kk_`jgf`ek`knflc[Y\n`j\kfk\jkpflie\n^Xk\nXp%Aldg`ekfk_\:fc[=lj`fe8[d`e`jkiXkfiXe[dXb\jli\k_Xk`kjkXikj%
585
586
CHAPTER
71
Integrating with SMS and IM
:i\Xk`e^Pfli=`ijk@D8ggc`ZXk`fe Now that you have your gateway set up, it would be great to test it and make sure that it works. To do so we will use a simple “Hello World” application. EFK
cXdb^c\BZhhV\Z function in your ^b#X[X to look like Listing 71.2. C`jk`e^.(%) ^b#X[X —Modifying the dc>cXdb^c\BZhhV\Z Function 1X[[jcXi^dccVbZ2ºdc>cXdb^c\BZhhV\Zº3 1X[Vg\jbZcicVbZ2º8;:kZciºineZ2ºhigjXiºgZfj^gZY2ºN:Hº3 1"""9idi]Z^gWjYYna^hi#º3 1X[Vg\jbZcicVbZ2º8;:kZciºineZ2ºhigjXiºgZfj^gZY2ºN:Hº3 1"""GZijgci]ZVXi^dcYZX^h^dc#"""3 1X[hZigZiKVajZ2higjXiCZl3 1X[hZigZiKVajZ#XdbbVcY2¹VXXZeiº3
C`jk`e^.(%* (continued) 1X[hZigZiKVajZ#7jYYn>928;:kZci#96I6#H:C9:G3 1X[hZigZiKVajZ#GZVhdc2¹7ZXVjhZlZVgZc^XZº3 1X[gZijgcgZiKVajZ3 1$X[[jcXi^dc3
Lj\iJkXkljDXeX^\d\ek Inside our gateway CFC you may have noticed a method called dc7jYYnHiVijh. This is called when one of the members of our buddy list changes their status. We will cache this information in the 6EEA>86I>DC scope, so that we can use this in the rest of our application. If we add the following code into our dc7jYYnHiVijh function we will have the status of all of our buddies available to the rest of the application: 1X[[jcXi^dccVbZ2ºdc7jYYnHiVijhº]^ci2ºEgZhZcXZhiVijhbZhhV\Zh[gdbdi]ZgjhZgh#º3 1X[Vg\jbZcicVbZ2º8;:kZciºineZ2ºhigjXiºgZfj^gZY2ºN:Hº3 1XÅdX`hXdeZ2º6EEA>86I>DCºi^bZdji2º&%ºineZ2º:M8AJH>K:º3 1X[hXg^ei3 $$8gZViZi]ZhiVijhhigjXijgZh^[i]ZnYdc¼iZm^hi# ^[CDIHigjXi@Zn:m^hih6EEA>86I>DC!¹WjYYnHiVijhºp 6EEA>86I>DC#WjYYnHiVijh2HigjXiCZl0 r
587
588
CHAPTER
71
Integrating with SMS and IM
^[CDIHigjXi@Zn:m^hih6EEA>86I>DC#WjYYnHiVijh!8;:kZci#9ViV#7J99NC6B:p 6EEA>86I>DC#WjYYnHiVijhP8;:kZci#9ViV# 7J99NC6B:R2HigjXiCZl0 r $$HVkZi]ZWjYYnhiVijhVcYi^bZhiVbe# 6EEA>86I>DC#WjYYnHiVijhP8;:kZci#9ViV#7J99NC6B:R#hiVijh28;:kZci#9ViV#7J99NI6IJH0 6EEA>86I>DC#WjYYnHiVijhP8;:kZci#9ViV#7J99NC6B:R#i^bZHiVbe28;:kZci#9ViV# I>B:HI6BE0 1$X[hXg^ei3 1$XÅdX`3 1$X[[jcXi^dc3
You will notice that we have put a 1XÅdX`3 around this code. This is just in case multiple users change their status at exactly the same time. We don’t want to overwrite one change with the other.
K_\@D>Xk\nXp?\cg\i As with all gateways, there is a helper class that carries out additional tasks that are specific to that gateway type. In the case of IM gateways there are four main areas of responsibility that our helper takes care of.
9l[[pC`jkDXeX^\d\ek One of the first things we want our application to do when it starts up is to check the status of our helpdesk staff. Typically all of our helpdesk staff will already be buddies in our application but it never hurts to check. Now our application is starting to grow, it is time to build an 6eea^XVi^dc#X[X file into our application. If you haven’t already got one, create an 6eea^XVi^dc#X[X file in your test directory. In our 6eea^XVi^dc#X[X (Listing 71.4), we will add some code that checks our list of users against the buddy list of the IM Gateway and requests authorization to add those users who are not buddies to the list when our application starts using the dc6eea^XVi^dcHiVgi function. To do this we need the VYY7jYYn helper function. EFK
C;QX[jh^dcQ\ViZlVnQXdcÄ\ directory on J2EE configurations, and in the X[TgddiQ\ViZlVnQXdcÄ\ directory on standard server configurations. Here’s an example: HBH8hZgkZgYZiV^ah ^e"VYYgZhh2&',#%#%#& edgi2,.%& hnhiZb"^Y2X[ eVhhldgY2X[ HdjgXZVYYgZhh[dgi]^hXa^Zci hdjgXZ"idc2& hdjgXZ"ce^2& hdjgXZ"VYYgZhh2***&'&' I]ZVYYgZhhgVc\Zi]^hhbeeXa^Zcil^aahZgkZ \e\iXk`e^JDJD\jjX^\j Once you have defined your gateway, it is time to write your first SMS application and start sending some text messages. For the time being, let’s put this in a test file: 1X[hXg^ei3 bh\2higjXiCZl0 bh\#XdbbVcY2¹hjWb^iº0 bh\#YZhi6YYgZhh2¹***&'()º0 bh\#h]dgiBZhhV\Z2¹=^[gdb8daY;jh^dcº0 gZi2hZcYcXdb^c\BZhhV\Zº3 1X[Vg\jbZcicVbZ2º8;:kZciºineZ2ºhigjXiºgZfj^gZY2ºN:Hº3 1"""