[Looking for Charlie's main web site?]

Speaking at CFUnited Express Chicago, and I'll see you at Max

For those going to Max, or who will be in the Chicago area but not going to Max, note that there's the CFUnited Express event going on also in Chicago the day before Max, Sunday Sept 30th. It's a day-long conference (9-5) with several speakers, including myself, Ray Camden, Shlomy Gantz, and others. These Express events are much more intimate than CFUnited (or certainly Max), so it's a great way to meet other CF developers.

I'll be presenting two talks, both of which I've presented before (so well-practiced):

After that, of course, we'll enjoy the rest of the week at Max, and I'll hope to see you there! :-)

How would you run code against multiple CF versions at once using IIS on XP?

If you use IIS on XP, have you ever wished you could put your code in one directory and run it against different versions of CF, easily. In this note, I show you how.

Someone asserted on a list that some code failed as of CF8, but I tested it against 8, 7, 6, and 5, and it worked the same in all. Hearing that, someone else asked, "Charlie, are you running all those on the same machine or on vmware?"

I assume that the reader, like many, is using IIS on XP, which doesn't let you have more than one web site, which might seem to make it impossible, though some may know the tricks I'll mention.

Of course, folks running on Apache, or IIS on Win2k3 or Win2k Server, would just say, "create different web sites, and install each CF version into a different web site".

Fair enough, but how do you solve this using IIS on XP (or Wink2 workstation), if you can't have multiple sites? That's what I explain below.

Before I go on, though, let me make an important for those who may not be aware: you certainly can run multiple versions of CF on a single machine. They each get installed in their own directories, with their own JVM (as of CF6). The challenge is just to avoid port conflicts and external web server conflicts.

But why not just use the built-in web server?

Sure, if you use the built-in web server available in CFMX since 6, then you can indeed run multiple CF versions each with their own web docroot without conflict.

But that's not the point here. That would cause each CF instance to have its own wwwroot, and you'd have to put your code there to run it on that version.

And I have even explained in a recent blog entry that you can get around that using virtual mappings in the JRun web server, pointing to the shared document directory. But sometimes you really want to use IIS for some reason, or you just don't want to have to remember to use the right port and virtual directory name configured for the built-in web server.

But you can have multiple web sites in XP, if you know how...

Yep, some will want to note that you can indeed create multiple web sites in XP, if you use the right tools. I've written about such tools before. It's just that you can't run them at once, so you have to enable/disable each time you want to run the test. To me, that more of a hassle than just doing the one-time configuration which I discuss below.

So how do you configure things using IIS on XP?

OK, I hope I've headed off complaints some may have. Oh, well, I should add one more: what I'm about to show you is definitely not supported by Adobe. Some might even argue against doing it. Certainly, if you have problems with things while trying to work this way, they're going to tell you to use a vanilla setup.

Still, it's worked for me for years. In fact, I first wrote about it in a CFDJ article back in Sep 03 (co-authored with Jeff Houser). That was written in the timeframe of people moving from CF5 to CFMX and wanting to set things up this way, but the concept still applies even for those moving from 7 to 8, or 6 to 7. It also mentioned using the same approach for running against BD as well, which means it would apply also to Railo and Smith, etc.

Finally, since writing that article, I've also realized a few things I could have added to the article, which further motivates me writing this entry.

How I set things up

So, as explained in the article (which shows you the actual steps in IIS), I configure different IIS virtual directories called _cf5, _cf6, _cf7, and _cf8. I set each to points their CFM extension (and related CF ones) to the appropriate web server extension that would be used if I'd configured each server to work with IIS (like C:\CFusion\BIN\ISCF.DLL for 5, C:\CFusionMX\runtime\lib\wsconfig\1\jrun.dll for 6, and so on).

More important, I have them all point at the same, single document root (in my case, c:\inetpub\wwwroot). That allows me to then run code in that single directory against different editions, using a url like http://localhost/_cf5/somefile.cfm, or http://localhost/_cf7/somefile.cfm, or the default http://localhost/somefile.cfm goes against CF8.

Note that you must run the web server connector for each CF edition from CFMX and above, since it only builds those jrun.dlls (I mentioned above) if you do that. See the CF docs ("Installing and Configuring ColdFusion" to learn how to run that, even after CF is installed, if you installed it using the built-in web server instead.

Before you do, though, as explained in the article, be sure to save off the path to the DLL for .cfm file extensions, as running the configuration tool will wipe over the previous path.

Some concerns using the CF Admin in this setup

There's something else to take note of about using the CF Admin (/cfide/administrator/index.cfm) when you set things up this way.

It has to do with whether, when you install each version, you tell CF to install using the built-in web server or using IIS.

In the former case, CF will put that version's CFIDE directory (and all its related files) into the wwwroot for that built-in CF server, such as c:\coldfusion8\wwwroot\ for CF8, or c:\cfusionmx7\wwwroot\ for CF7.

In the latter case (if you tell CF during installation to use IIS), then CF will place those files into the IIS docroot you name. Assuming you would always choose that c:\inetpub\wwwroot directory, that means that its CFIDE directory will be replaced with whatever is the last CF version you install.

And that means that even if using the virtual directories above, they'll all point to the last CFIDE version, which won't work (the CF Admin can only run in the version for which it's created).

Either way, you can solve this by creating yet another virtual directory, for CFIDE, inside the version-specific virtual directories above.

So if during the installation of 6, 7, or 8 you told CF to use the built-in web server, you'd point the new CFIDE virtual directory to the builtin web server's CFIDE. For my _CF6, for instance, I'd create a CFIDE virtual directory within that to point at c:\cfusionmx\wwwroot\CFIDE.

If instead you choose to install each version using IIS, then just as you needed to save off the file extension's path to the web server DLL, you would similarly need to remember before each install to save off a copy the CFIDE directory for the previous release. This is especially key for CF5, since there is no concept of a built-in web server for that.

Back when I installed CFMX 6, before doing so, I copied the CFIDE directory to call it CFIDE5 instead. (Sure, you could do a rename, but only JUST before you installed, in case you need it.) Then I created the CFIDE VD within the _CF5 VD to point to that.

It may be worth noting here that if you do install CF 6/7/8 using the built-in web server initially, and then use the web server configurator tool to then connect them to IIS, that does not move the CFIDE from the built-in web server root to the IIS docroot. So again you will need to point your CFIDE virtual directory to that CFIDE in the built-in web server.

Why not just use the built-in web server for the CF Admin?

Of course, you could just use the built-in web server to access the Admin instead, even if you are otherwise running code via IIS.

And going back to the original writer, you could indeed also do this using VMWARE. (I've written about how versions of it and Virtual PC are now free.) It might be overkill, though. Again, you don't need to worry about running multiple versions of CF on a single server. It's all just about avoiding port conflicts and potential external web server conflicts.

That's what this has been about all about: how to run all your code via IIS against multiple version of CF, all from a single directory.

Conclusion

Did this help you? Let me know. Did I forget something? Got a complaint? (People seem to love that opportunity. Go for it.) I hope it has helped some of you. It's certainly helped me, and others who I've shown it to.

Testing code in CF8 and earlier releases--in the same code directory

As folks contemplate moving to CF8 from 6 or 7, they may know that they can run these releases alongside each other--as long as you use a separate web server (or web site in servers that support it) configured to hand CFML requests to each CF server. Since CF6, CF has included a built-in web server to help with this very issue, especially on servers (like IIS on XP) where you can't have more than one site.

But what if you want to test some code in a single directory against one or more editions? Is that possible? I mean, let's say you have CF7 setup against IIS, and your code is in the c:\inetpub\wwwroot? And you've installed CF 8 for testing using its built-in web server, which runs on port 8500 (or whatever you chose) and finds its code in, for instance, c:\coldfusion8\wwwroot.

How would you have CF8 look at the code you've long had running in the IIS root? (or Apache, or a virtual directory you've setup for use by either external web server). Do you have to move the code around among these directories to test it on different versions of CF? No, you don't.

The trick is in the jrun-web.xml, which you can find in cfusionmx_home]\wwwroot\WEB-INF\jrun-web.xml . You can add a new "virtual-mapping" entry there, naming a new "alias" which points to files outside the normal CF-based wwwroot:

<virtual-mapping>
<resource-path>/inet/*</resource-path>
<system-path>C:/inetpub/wwwroot/</system-path>
</virtual-mapping>

So now a request for http://localhost:8500/inet/ will look instead in the inetpub/wwwroot, or wherever you point it.

Update: Note that when you use the resource-path, it's case-sensitive, even on Windows, so http://localhost:8500/INET/ would not be the same.

Of course, this works also if you set up CF8 to run via your built-in web server, but setup CF 7 or 6 to run on its own built-in web server. And of course, if you're savvy enough you may figure out how to run things so that you can run all 3 using an external web server.

There are a couple of potential challenges with this technique. For one thing, if your code has hard-coded references (such as hyperlinks, images, CFLOCATIONS, etc.) to either run on a particular host (without the port) or at a particular root-relative path, then this introduction of a new port or the /inet/ alias may hamper it working. That's not a "CF" problem but rather a coding one. Your stuck then.

But it certainly works well for testing individual files. I do it all the time and have for years. Indeed, I'll share, for the sake of posterity, that this modifying of the jrun-web.xml is something I first wrote about back in 2002, but many may have missed when such info was being shared.

I'm going to go back and reprise a lot of those "oldies but goodies", spread across a few different blogs I've had over the past several years. I think I'll call them "carehart classics".

Resources for getting into the Multiserver (multiple instance) implementation of CF

You may have heard of the new Multiserver deployment option that was introduced in CFMX 6.1, also known as "multiple instances". It can bring tremendous performance and reliability improvements, allowing you to segregate apps on a single server either by function, or reliability, and so on. It can also help you manage memory more effectively.

Since many people may only be considering the feature now (either only now moving to 6.1 or 7, or 8), I want to share some resources if you're new to it. (The question came up on a list, and I offered the info there, so thought I'd pass it along here.)

First, there are a couple of articles from that time 6.1 frame:

"Introducing Multiple Server Instances in ColdFusion MX 6.1", by Tim Buntel

"Using Multiple Instances with ColdFusion MX Enterprise 6.1" video

Now, CF7 did introduce the new Instance Manager within the Admin, and that (and instances in general) is covered in the CF manual:

Configuring and Administering ColdFusion MX (Chapter 7, "Using Multiple Server Instances")

Finally, there is also a new Adobe article as of CF7:

http://www.adobe.com/products/coldfusion/whitepapers/pdf/cfmx7_mulitpleinstances.pdf

There are certainly other articles folks have done in the CFDJ or at CommunityMX.com, but these should get you started.

Even though it's old news to some, it does seem that like many things, use of instances is something that may have been missed by folks. I've been contemplating a new user group presentation on the topic. Nothing new for CF8, but it seems people are considering things now that they may have ignored when 6, 6.1, or 7 came out (which is why I did my daylong class at CFUnited on what was new in 6 and 7 that folks may have missed).

One last point, if those don't make it: if you're running on Windows, don't try to create an instance with a JVM heap greater than about 1.3 GB. Though Windows should allow 2GB per app, this is just a number many found that beyond which CF won't start. Hope that all helps.

CF8 Admin Changes: A compendium of new/changed features since 7.02

Are you aware of all the changes that have been made in the CF Admin as of CF8? You may have seen mentions of little changes in CF8 (indeed, I've done a full hour user group talk on hidden gems), and while I mention some changes in the CF8 Admin (as I or others have noticed them), I've not seen any definitive list (from Adobe or the community) of all the changes (small and large) that might have occurred in the CF Admin interface. I figured I'd take up that challenge.

I've gone through and compared the CF Admin between 7.02 admin 8, and found changes that reflect:

  • new major features you've probably heard about (whether to enable "per app settings"; limits on the number of cfthread threads; options to enable/control the new interactive step debugger; support of the new Server monitor; support of per-user access to the Admin and RDS)
  • new minor features you may have missed (options to "disable CFC type check" and "disable access to internal CF java components"; options to limit the number of simultaneous requests from Flash Remoting and web services clients and CFC methods called from a URL; options to set request queue timeouts and set jrun request limits; new options to control mail server authentication; new db drivers; new option to log activity on enterprise databases; new option to perform a validation query when a connection from the pool is first used/reused; new ajax debugger window; ability to pause a scheduled task; 3 new flex-based gateways; minor additions in CAR file creation)
  • realignment of related settings (request tuning settings)
  • renaming of various pages and settings

Here are all the changes I could find, discussed per page:

A. Server Settings Section

Settings Page

  • "Maximum number of simultaneous requests", "Maximum number of report threads", moved to new Request Tuning Page
  • "Maximum size of post data" moved to bottom of this same page
  • New "Enable Per App Settings", "Disable CFC Type Check", "Disable access to internal ColdFusion Java components", and "Watch configuration files for changes" (latter for WebSphere ND)

New Request Tuning Page

  • Besides holding the "Maximum number of simultaneous requests" setting (renamed here in CF8 as "Template" requests) moved from the old Settings page, this page now permits setting limits on number of simultaneous requests from flash remoting and web service clients, as well as CFC function requests (not calls to CFC methods from CFML but those made via a URL, such as from a browser or Ajax client, etc, when not using ?wsdl)
  • Besides holding the "Maximum number of simultaneous report threads" setting (renamed here in CF8 to add "simultaneous") moved from the old Settings page, this page also permits setting limits on number of simultaneous CFTHREAD threads
  • Page adds 2 new "Queue Timeout" settings/li>
  • Page adds 2 new "JRun Master Request" limits

Mail Page

  • New Username and password fields to hold SMTP server authentication info (previously, had to know how to add it to the mail server name using username@password:servername in the mail server field). Use of password field offers protection of password from someone watching over your shoulder.
  • New "Connection Timeout" and "Enable SSL Socket connections to mail server" and "Enable TLS connection to mail server" options, each permitting greater security and control over authentication to SMTP servers (particularly Google mail servers)

B. Data & Services Section

Data Sources Page

  • New driver types: "Apache Derby Client", "Apache Derby Embedded", to support the newly available Apache Derby database, and "MySQL 4/5" (in addition to existing MySQL 3) and "PostgreSQL"
  • In "Advanced Settings", new "Log Activity" option (to log database activity to DB) for Enterprise drivers (SQL Server, Oracle, Informix, Sybase, and DB2).
  • In "Advanced Settings", new "Validation Query" option (called when a connection from the pool is reused), available for use with all driver types

Verity K2 Server Page

In "Advanced Settings", new option to enter K2 Admin Username and Password.

C. Debugging & Logging Section

Debugging Output Page

  • Page name changed from just "Debugging Settings" (due to addition of new "Debugger Settings" page listed below).
  • New "Enable AJAX Debug Log Window" option, which allows display of the AJAX debug log window when the cfdebug flag is passed in the URL (also relies on IP address settings to control who sees this)
  • "Enable Debugging" option renamed to "Enable Request Debugging Output"

New Debugger Settings Page

Enable, configure, and control interactive step debugger in Eclipse.

Scheduled Tasks Page

New option to pause a given scheduled task (new button in list of buttons to left of each scheduled task)

Systems Probes Page

Field for "Notifications Sent From" renamed to simply "E-mail".

Code Analyzer Page

Changed to list CF8 tags and functions in "Advanced Options" page.

D. New Server Monitoring Section

Offers links to the new Server Monitor and Multiserver Monitor.

E. Event Gateways Section (used to be Enterprise-only)

Gateway Types Page

New Flex-based gateways: "DataManagement", "DataServicesMessaging", "FMS"

F. Security Section

Administrator Page (renamed from "CF Admin Password" page)

Offers new interface to use either a single Admin password (as before), or separate username/password (per authorized admin user, as enabled in new "User Manager" page listed below), or no password required at all

RDS Page (renamed from "RDS Password" page)

Offers new interface to use either a single RDS password (as before), or separate username/password (per authorized RDS user, as enabled in new "User Manager" page listed below), or no password required at all

Security Sandbox Page

"CF Tags" and "CF Functions" tabs for adding/editing a sandbox have been changed to list CF8 tags and functions.

New User Manager Page

Enables adding users who should be given access to either RDS, CF Admin, or Admin API functionality.

G. Packaging & Deployment Section

ColdFusion Archives Page

When adding/editing an archive, the popup window that is shown offers several sections, and the following changes have been observed:
  • Server Settings: "Locking" section has been removed, while "Watcher Settings", "Server Monitor Settings", and "System Probes" have been added
  • New "Web Services" settings page, with provided "pre-restore" and "post-restore" lists

J2EE Archives Page

When adding/editing an archive, there is a new "Previous Serial Number (if upgrade)" option.

Where to learn more

To find out more about these changes, see the online help available in the CF Admin, available on each admin page.

Or see the ColdFusion documentation manual, "Administering and Configuring ColdFusion 8", available at CF docs page.

I realize that some reading this will be moving from CF 6, 6.1, 7, or 7.01. I'm afraid I can't detail here all the changes between those releases. I have, however, got a day-long class I offered at CFUnited on "New in CFMX 6/7: What you may have missed", where I do outline changes in each of those releases (and intervening updaters). If you're interested in taking that class, drop me a note or leave a comment here. I am thinking of offering it as an online class (and plan to do the same regarding all changes in CF8--outside of the Admin). Hope all this helps others.

Charlie Arehart offers new per-minute phone-based support service

Ever felt stumped trying to solve a CF problem? You've tried everything? Searched the web? Asked on forums and lists, and you're still stuck? Or maybe you're just pressed for time.

Maybe you've wished you could hire someone with more experience but can't justify a high hourly rate. Of course, with so many web tools available to share a desktop, travel need no longer be a significant issue. Sometimes, it could help to simply have someone "look over your shoulder" via the web to resolve a problem.

Recognizing all those challenges, I've created a new service that I'm tentatively calling "AskCharlie", to be able to offer just such assistance.

Via buttons on my site or an 888 number you call, you can arrange to speak with me by phone (and optionally join me in a shared desktop session) to solve some knotty problem.

Best of all, it's very low cost and at a per minute rate (first-time callers can use a 10 minutes free option, and everyone gets a money-back guarantee). That and more are explained on my site:

http://www.carehart.org/askcharlie/

There you can learn more about why I did it, how it works, how the remote desktop sharing assistance works (no problem with firewalls, for instance), and more.

I'd welcome your thoughts on what you think of the idea.

Reloading CF web services programmatically, using the CF7 Admin API

I'm surprised to not see much out there about how to reload or refresh CF's cached WSDL proxy for calling a web service, at least programmatically using the new CF 7 Admin API. Perhaps it's because people have been tripped up, or simply haven't explored it. Either way, I'd like to offer here the code you need, and also point out some tips and traps.

Introduction: Why You Would Want to

As background, someone reported having a problem calling a web service from CFML, and a solution suggested was that the person reload or refresh the web service using the CFMX Admin console (in the "Data & Services" > "Web Services" nav bar tab. There, you'll find any web services that have been called from CF (which is often a surprise to folks that they're tracked there). For each listed web service, there are 3 buttons and the middle one does a refresh (which means it goes and grabs the WSDL and builds a local java proxy stub, which is used when you then invoke the web service).

But one may then wonder how to do that programmatically, without having to open the Admin console. In CFMX 6.1, you could use the undocumented ServiceFactory, as I'll show below to those still using that. But since that's being deprecated, you really ought to learn the new CF7 approach.

The CF 7 Admin API Approach

As of CFMX 7, we are expected to use the new Admin API, a set of CFCs provided with CFMX 7, which offer a formal, secured API for accessing functionality otherwise offered in the Admin console.

So how would one do that to refresh a web service? Well, there is an extensions.cfc in the Admin API (a set of CFCs in the webroot's /CFIDE/adminapi/ directory), and it has a reloadWebService method that's just the trick. How did I know that? You can call the built-in CFC documentor by browsing the CFC directly:

http://<em>[servername]</em>/cfide/adminapi/extensions.cfc

Before you can call that, though, note that you do need to "login" to the Admin API by calling the login method of the administrator.cfc first. (Check out its docs to learn more.)

But to save you that effort, here's some code. (As always there are several ways to call a CFC and its methods (using CFINVOKE or CFOBJECT, or createObject either within CFSCRIPT or not), but here's at least one approach.):

<cfset createObject("component","cfide.adminapi.administrator").login("youradminpw")>
<cfset ws = createobject("component","CFIDE.adminapi.extensions")>
<cfset ws.reloadWebService(name="<em>webservicename</em>",path="<em>WSDLurl</em>")>

Note that you need to specify your own admin password in the first line, and in the last line you need to specify a web service name and its WSDL URL.

What's with this notion of passing in a web service "name"?

As you contemplate that code, you will certainly know what the WSDL URL is, since it's the same one you'd use in a CFINVOKE or CFOBJECT/createobject call of the web service itself. But what's the "name" requested here? Well, that can trip you up and it deserves further discussion, as it has several ramifications as I'll explain here.

The name is the name shown in the Admin console for the given web service. The trick/trap is that if you never open and change the Admin console entry for this web service, then the name will simply be the same value as the WSDL URL. But there's more to understand.

First, if you didn't know it, one can edit that "name" in the Admin console, and then one can even use that "name" as an alternative (or "alias") to the web service WSDL URL when invoking the web service from CFML. That's a whole separate subject which I've covered in user group talks in the past.

But assuming that no one has modified the web service name (or for reasons I'll explain in a moment, if you are not using such an alias name when you invoke the web service), then you can presume the name and WSDL URL to be the same. As an example, one could change the last line above to:

Getting Web Service Names Programmatically

Now may wonder, "can I get the web service name programmatically?" You can. But here's where it gets a little confusing. There is an available getwebservices method of the extensions.cfc. And according to the docs, you can either pass in the "name" of the webservice, or leave it off to get all web services. If we don't know the name, then we may think we'd want to use the latter approach. But I find that it doesn't quite work as straightforwardly as it seems.

First, I tried calling getwebservices() without a name:

<cfset createObject("component","cfide.adminapi.administrator").login("youradminpw")>
<cfset ws = createobject("component","CFIDE.adminapi.extensions")>
<cfdump var="#ws.getwebservices()#">

Sadly, it returned an empty dump as a result. Yet I had several web services listed in my admin console. Here's the thing: none had a name. I then renamed one of them (to "test"), and tried it again, and suddenly the call did return an array of structures (1, in my case) with the name and WSDL URL.

Hmm. So it seems instead that the getwebservices() ought perhaps instead be named getnamedwebservices(), since it only returns web services whose names have been changed (been given an alias).

Still, though, if I do pass in a name, as the docs suggest, then I do indeed get the same result:

<cfset createObject("component","cfide.adminapi.administrator").login("youradminpw")>
<cfset ws = createobject("component","CFIDE.adminapi.extensions")>
<cfdump var="#ws.getwebservices("test")#">

Now, you may wonder: "if I can't a listing unless I know the name, or can only get a list of 'all' of them if they are named, then how might I get the info for ones that have no name or whose name I don't know?"

Good question. And guess what I've found? A couple of important things.

First, I've found that you can also pass in the WSDL URL, even for a web service that's been renamed with an alias like "test", such that this works:

<cfset createObject("component","cfide.adminapi.administrator").login("youradminpw")>
<cfset ws = createobject("component","CFIDE.adminapi.extensions")>
<cfdump var="#ws.getwebservices("http://ws.invesbot.com/stockquotes.asmx?WSDL")#">

Again, that's not the web service name but the WSDL URL. And the resulting dump shows the name and that URL. So the API docs on this are a little misleading.

Be sure to refresh the "right" webservice: the one you'd really try calling

But perhaps a more important thing is that I found that you can have a web service entry for the SAME WSDL URL but with different names/aliases. Why is this important? Because you want to make sure you refresh whichever one you're using.

This goes back to my point above when I introduced the refreshWebService method: you need to give it the name as YOU call the web service, otherwise you'll be refreshing a different proxy stub and won't see the benefit you expect.

If you use the WSDL URL when you invoke the web service, then that will create a proxy stub with that "name", and therefore you want to use that as the "name" when you refresh it.

If you rename a web service in the Admin console, and then use that when you invoke the web service, then you want to use that as the "name" when you refresh it.

Refreshing Web Services Using the ServiceFactory

Since some folks reading this may not have moved to CF 7, let me show how you could do the same using CFMX 6/6.1 (or indeed 7, since it still works there). It's important to note, however, that using the ServiceFactory is not only not documented but it's also not supported. It has security problems (since there's no need to provide the admin password as you must in the Admin API). Also, it may eventually be obsoleted or otherwise restricted.

Still, since it's been documented by others in the past and is readily available on the web, I'll offer it here:

<cfobject action="CREATE" type="JAVA" class="coldfusion.server.ServiceFactory" name="ServiceFactory">
<cfset ServiceFactory.getXMLRPCService().refreshWebService("<em>webservicename</em>")>

Now, you'll notice that I've indicated that the value passed into the refreshWebService method is the webservicename. That's because it works just like the Admin API reloadWebService discussed at the top here. Be sure to specify the name as you would use it in the invocation of the web service (whether an alias or the full URL).

How to Confirm That Refreshing is Working

As you try these three approaches (Admin button, Admin API, and ServiceFactory), you will probably benefit greatly from being able to see for sure that the refresh/reload is updating the java proxy/stub class files. Where do you find them? They're stored in a "stubs" directory under your CFMX install directory, such as C:\CFusionMX\stubs or C:\CFusionMX7\stubs.

Then, under that, you will find directory names such as WS141836989, or a name that's the same as the alias/name you give to a web service in the Admin console. Inside those directories you will find other subdirectories, eventually finding some that hold the .class files representing the objects available in the web service. It's those .class files whose date/time stamp you want to see changing when you do a refresh/reload.

I'll note that there's no mapping or indication of that WSnnnn directory name, to know which one holds the web service you're interested in. I guess you just have to find the right one by looking for one whose class names map to the web service object you're calling. (If anyone knows a better connection, please do share it.)

Finally, I think it may be worth clarifying that when you do a refresh/reload of a web service using the approaches above, you need to have first made a call to that web service from CFML (or entered it manually in the admin console).

Hope all that's helpful.

Summary of Notes for Adobe Folks

Before I end, in case any Adobe folks are listening, here is a restatement (and expansion) of the couple of observations I made about wrong or undocumented functionality. This is for both the docs group and the engineers, since this is also about internal API documentation returned by the CFCs and their functionality:

  • getwebservices() only returns web services that have a name that was changed, whereas the API doc says it returns "all web services", so it either is working incorrectly or ought to be called getnamedwebservices instead
  • though not documented, getwebservices("wsdlurl") works also. The API docs say that it should only take a name (and I tested this against a web service where I had renamed it, so it was not getting it "by name")
  • if you do consider renaming the getwebservices() method to be called getnamedwebservices(), you might then also want to rename getwebservices(name) to getwebservice (singular), since it just gets one webservice
  • it would be nice to be able to refresh ALL webservices that use a given WSDL URL at once, perhaps by new method that accepts URL rather than name (and works for all occurrences of that URL in the cache, whether named with an alias or not)

Understanding (and monitoring) the CF template cache

Adobe CF team member Ashwin has posted an entry offering some useful insights into the inner workings of the CF template cache. More detail from Adobe folks is of course always welcome. Thanks, Aswin.

I've posted a comment there about how to measure and report on whether and when template cache misses occur. (Again, read his post for more on what a means.)

I would have posted it as a trackback from here, but I don't see how to do that in BlogCFC. So instead, I'm pointing you to it this way. :-)

To save you the trouble, if you just want to know how to measure it, here's what I wrote:

Thanks, Ashwin. More detail from Adobe folks is of course always welcome.

But I do think it's useful to point out also how one can measure and report on whether and when template cache misses occur. There are at least two.

First, it's reported in the command-line CFSTAT tool as CP/Sec (for cache pops per second), and reports both a current and highwater mark. (Of course, you must enable CFSTAT support in the CF Admin, and the cfstat is in the cfusion/bin or cfusionmx/bin.)

It's also reported in the Windows Performance Monitor, by way of the ColdFusion/ColdFusion MX "performance object" counter called "Cache Pops/Sec" (again, assuming that you've enabled Perfmon support in the CF Admin).

With perfmon's ability to create logs and alerts, it should be easy for someone to create a mechanism to track if you ever have a non-zero value, which would suggest increasing the template cache size.

I meant also to mention that there is an old but still useful Allaire technote offering some more insight into caching, including using CFSTAT and more.

Solving error connecting to SQL Server 2005 from CFMX 6.1/7 on Localhost

Are you getting the error, "Connection refused" or "Error establishing socket to host and port", trying to connect to a SQL Server 2005 database in CFMX 6.1 or 7? Or the error, "SQL Server does not exist or access denied", in CF5 using OLEDB? I have a solution.

No, I'm not just going to recommend creating an ODBC datasource, as many others have. :-) There is a real solution. The short answer is to open the "SQL Server Configuration Manager" in SQL Server 2005, and ensure that TCP/IP is enabled as a protocol.

The rest of this entry explains additional details, such as how to find and make that change, what specific errors you get, and how I found the information, in case any of it helps others.

I should add that I don't have SQL 2000 against which to test how things are similar or different, but I do point to some CFMX docs that may apply to that version. In any case, hope this will serve all those CFML developers making the move to SQL Server 2005.

The Errors You May See

To help ensure that future readers can find this entry more readily when doing web searching, let me offer details on the error. The problem I'm referring to is if you get any of the following errors.

In the CFMX 7 admin, when adding, editing, or verifying a SQL Server 2005 datasource, you get the following error:

Connection verification failed for data source: blogcfcsql java.sql.SQLException: [Macromedia][SQLServer JDBC Driver]Error establishing socket. Connection refused: connect The root cause was that: java.sql.SQLException: [Macromedia][SQLServer JDBC Driver]Error establishing socket. Connection refused: connect

Or if you run code on CFMX 7 that tries to use such a datasource and get:

Error Executing Database Query. Macromedia][SQLServer JDBC Driver]Error establishing socket. Connection refused: connect

In CFMX 6.1 you get this slightly different error when adding or editing the DSN in the admin:

Connection verification failed for data source: blogcfcsql []java.sql.SQLException: [Macromedia][SQLServer JDBC Driver]Error establishing socket. Connection refused: connect The root cause was that: java.sql.SQLException: [Macromedia][SQLServer JDBC Driver]Error establishing socket. Connection refused: connect

When you simply verify the DSN in CFMX 6.1, it only says "error" in the status column. You need to edit and submit the DSN to see the error above.

And if you run code trying to use such a datasource in CFMX 6.1, you get:

[Macromedia][SQLServer JDBC Driver]Error establishing socket. Connection refused: connect

I don't have CFMX 6.0 installed to see what happens there.

Lastly, in CF5, while most use ODBC datasources there, if you did try to create an OLEDB datasource using the SQLOLEDB provider, in the circumstance I'm describing it would just say "failed" if you try to verify it, and "The connection to the data source failed" if you edit the DSN and submit it.

In code using the DSN you would get:

OLEDB Error Code = 17 [DBNETLIB][ConnectionOpen (Connect()).]SQL Server does not exist or access denied.

Update for CF8

Here's what the error is in CF8 might look like:

Connection verification failed for data source: blogcfcsql java.sql.SQLException: [Macromedia][SQLServer JDBC Driver]Error establishing socket to host and port: [server]:[port]. Reason: Connection refused: connect The root cause was that: java.sql.SQLException: [Macromedia][SQLServer JDBC Driver]Error establishing socket to host and port: [server]:[port]. Reason: Connection refused: connect

So, those are the errors. What's the solution? :-)

Finding the Solution

After some digging around, where folks offered all sorts of remedies (including recommending you just punt and create an ODBC datasource instead), I finally found the CFMX docs, Configuring and Administering ColdFusion MX, in its section, "Connecting to Microsoft SQL Server":

http://livedocs.macromedia.com/coldfusion/7/htmldocs/00001743.htm#1278307

There it offered a few recommendations where "the following situations can cause a Connection Refused error". The one that caught my attention was:

SQL Server does not enable the TCP/IP protocol. This problem can happen when SQL Server is on the same computer as ColdFusion MX.

Well I am running both CFMX and SQL Server on my laptop (development mode for each), so this sounded encouraging. It would also explain why different folks experience different things, if they have SQL running elsewhere and/or in non-development mode. Indeed, further reading (discussed later) shows that there are differences in implementations of SQL 2005 that would influence whether you'd get this error.

Anyway, the CFMX docs go on to say you should make sure that TCP/IP is not listed as a "disabled protocol", which it indicated can happen in a local (development) mode installation of SQL Server.

Unfortunately, the steps they show to check and correct that are not appropriate for SQL Server 2005. (I will add a comment there pointing back to this blog entry.)

But in searching the SQL 2k5 books online, I found an entry that does explain this issue (following is a local link if you have BOL installed yourself):

ms-help://MS.SQLCC.v9/MS.SQLSVR.v9.en/udb9/html/ad98873f-8478-4bce-8abf-c24f5d111144.htm

It explains how things will be set for different versions of SQL Server 2005 (Enterprise, Standard, Workgroup, Developer, Evaluation, Express) and whether you have a previous SQL Server version that you are or are not upgrading. Each of these has different defaults for if TCP/IP is enabled.

The Solution in SQL Server 2005

BOL goes on to indicate that we need to go into the SQL Server Configuration Manager to configure the network protocols. There are 2 ways to do this: either right-click on the server in Mgt Studio and choose "SQL Server Configuration Manager" or use Start>Programs>Microsoft SQL Server 2005>Configuration Tools>SQL Server Configuration Manager.

From the window that opens, select the "SQL Server 2005 Network Configuration" node, and its "Protocols For [yourserver]". That lists the various protocols (including TCP/IP and named pipes), and sure enough, for me it showed disabled.

I right-clicked the TCP/IP protocol name and andose "enable", which reminded that I needed to restart the SQL Server for the change to take effect (right-click on the server in SQL Management Studio and choose "restart"). I did that, and then reran my code and all was well (and the datasource would now verify in the Admin console.)

Phew! Hope this helps someone else.

Update

I was working on another machine where I had this error, and this time, I had to take one more step in enabling the port, as the step above just wasn't enough.

On that TCP/IP protocol, where I right-clicked to enable, that right-click also offers a Properties option (which is another way you could choose to enable/disable the protocol). But the window that pops up also has a IP Addresses tab. Choosing that, I saw several various indications of IP addresses, with settings to both make them active and enabled, as well as indicate the port they should use. I tried changing various ones, but in the end found that the only solution was to change the last one, IPAll, and add my SQL Server port (1433) in its TCP Port field. After doing that, and restarting, all was well.

There may be (indeed, likely are) important security considerations that should go into enabling that option. Since this is just my local development box, in a firewall, I won't bother to investigate the, but others here should.

Some Closing Additional Thoughts

Again, some posts I'd found suggested that the solution was to use an ODBC connection instead. That surely works, but most regard an ODBC connection as less performant, and involving more communications overhead per transaction. Also, I have seen code that failed using an ODBC connection that worked fine with a SQL Server connection.

I should also note that you can change this another way, using the new SQL 2005 "Surface Area Configuration" wizard, and choosing "Configure Surface Area for [your server]", then choose "Surface Area Configuration for Services and connections" and then in its window choose "[your server]>Database Engine>Remote Connections and changing to "Local and Remote Connections" to enable TCP/IP.

I'll note that for some reason, BlueDragon's SQL Server driver (based on New Atlanta's JTurbo Type 4 JDBC driver for SQL Server) didn't have this problem. Perhaps someone with more experience in the underlying implementation can explain why the two are so different.

Finally, one other comment: if the error you're getting is instead:

Error Executing Database Query. [Macromedia][SQLServefr JDBC Driver]Error establishing socket. Unknown host: (local)

That is a different problem. The online help in the CFMX Admin suggests that you can name the server as "(local)", but I find I get the aforementioned error. Changing it to the server name or IP, such as 127.0.0.1 for my localhost, solved the problem. (The help also indicates this an option, so I'm just speaking to those who try the "(local)" value.)

One other thing: another problem could be that SQL Server is listening on a port other than what you think. Don't presume it's the standard 1433. Someone could have changed it on install, for security reasons, or some other config feature could have changed it. You can see what the port is by using that same SQL Server Configuration Manager, but rather than use the "SQL Server 2005 Network Configuration" option in the left tree, choose the "Client Protocols", then right-click on TCP, and choose Properties. It will list the "Default Port". Hope all that's helpful to some.

BlogCFC was created by Raymond Camden. This blog is running version 5.005.