Wednesday, February 20, 2008

Directory Watcher talk by Dave Ferguson

It looks like I will be giving a talk to the Online ColdFusion Meetup next week (details to follow). In browsing around the meetup site, I decided to watch a talk about the Directory Watcher Event Gateway, one of the example gateways we shipped in ColdFusion 7 (& 8). I am always impressed at how useful folks find this gateway as I wrote it on a whim in just a few hours because we wanted to provide some source code examples for those who wanted to write their own gateway.

Anyway, if you do watch Dave's talk, there are a few questions and quirks he mentions that I wanted to try and clear up.

First, note that the Java source for this gateway is shipped with every copy of CF in /gateway/src/examples/watcher. I am still waiting for someone else to fix the problem of slow uploaded files triggering the "ADD" event before it is done writing the file. Dave gives a CFML/Java based work around for this problem in his talk (and makes the files available on his blog here).

Dave notes that the "Out"count in the CF administrator is always 0 for this gateway. This is the number of messages/events that the gateway has sent, well, out. For instance how many times SendGatewayMessage() was called for this gateway. Since the Directory Watcher doesn't do outgoing messages (see line 187), this count will of course always be zero.

Dave mentioned that when he returns something from (in his case) one of the onAdd, onChange or onDelete functions, he gets a meaningless error in the logs. I filed a bug on this for Dave (#71311). The problem is that as a convenience the gateway system will take the return value of an event processing CFC function and send that "out" to the gateway. For instance if you receive an SMS or IM message to one of those gateways, you can return a Struct with a reply message from the onIncomingMessage function and the system will (in effect) call SendGatewayMessage() on that gateway with that struct. Since he was returning a simple value (i.e. "1") CF tries to make that a Struct, fails and reports the strange error. It *should* ignore that return value and log a warning (in the eventgateway.log) that it is doing this.

Dave was asked about timeouts for the CFC processing functions. Event Gateway CFC function calls are subject to the same timeout value as ColdFusion requests. A gateway can override this value (in the Java code) by calling CFEvent.setCfcTimeOut(). Otherwise the timeout is the same as for "regular" CFML page requests.

There was a question about file renames and what the Directory Watcher does when it sees this. The watcher does in fact report an ADD and a DELETE event when you change the name of a file. This is by design and I verified this on ColdFusion 7 and 8.

Hope this info helps those looking for more information about this gateway.

14 comments:

Brian said...

I am trying to use Directory Watcher on a directory on another server that we let users have direct access to. Dave said not to try it, but I need it. How do I make the directory-watcher.cfg directory variable= [another server]? I can connect to another drive using directory=E:/WebDocuments/queue . But another mapped drive like Y:/WebDocuments/queue fails. Same with using a UNC I think.

Thanks.

Tom said...

You must run ColdFusion as a user which has access to the network resource in question. On Windows this means opening up the Services control panel and editing the ColdFusion service to run under an account that has permissions to access the network.

The default "Local System account" does not have permission to access network file paths.

Once you do this a UNC path or mapped drive should work for the directory watcher.

Brian said...

Thanks. That did the trick for accessing the remote server using the unc code directory=\\\\1.1.1...\\test\\files. Still have the same error with my CFCs being on another drive on the CF server not working.

Apr 2, 2008 9:11 AM Error Thread-24
Error invoking CFC for gateway DocImagingDirectoryWatcher: Invalid list index 6.. In function ListGetAt(list, index [, delimiters]), the value of index, 6, is not a valid as the first argument (this list has 0 elements). Valid indexes are in the range 1 through the number of elements in the list.

Tom said...

@Brian That error is because you have an error in you CFML code. Specifically you are calling ListGetAt() on a list that has les than 6 items in it.

Brian said...

Actually I don't think so. I have the following in my start of my CFC:
cfcomponent output="no"
cffunction NAME="onAdd" OUTPUT="NO"
CFARGUMENT NAME="CFEvent" TYPE="struct" REQUIRED="yes"
/cffunction
cffunction name="onChange" output="no"
/cffunction
cffunction name="onDelete" output="no"
/cffunction
/cfcomponent

Had to remove the tags < and > here.

I guess my earlier post that I just referenced did not make it this morning. Anyway, the issue is that I get an error (referenced in the above post) in the eventgateway.log file if my cfc is anywhere except on the the drive that CF is installed in. The error occurs even on the same server. I move this same CFC onto the CF install drive, change the link to it and I get no error.

Brian said...

I'm still trying to figure this out about the CFC. I do notice in the eventgateway.log file that when I start/restart any directory watcher gateway that it says something like the following:
"Restarting Gateway: ID=DocImagingDirectoryWatcher, Class=examples.watcher.DirectoryWatcherGateway
I looked at this Class file and did not see any ListGetAt calls, nor have I ever used the function as best I can recall however there are some import statements and the like in that file. Is it using this file? Do I need to modify it? I am using Enterprise edition CF 8,0,0,176276 and update level ...chf8000002.jar. Java version 1.6.0_01. Java Class Version 50.0

Tom said...

@Brian That is strange. You should not need to modify the Java source for the DirectoryWatcher gateway itself.

Check the exception.log file in the ColdFusion log directory to see if the stack trace for this error is there. This might give you more clues as to what code is stumbling here.

Brian said...

no errors there or any of the other logs.

Have you been able to run a directorywatcher gateway CFC in a location on a drive other than your CF Install drive?

Tony said...

any idea why the onChange event in cf8 would fire twice. once for the current change, and once for the previous change? here's the scenario...

1. .txt file on server
2. if i make a change my cfc emails me to let me know
3. i get two emails. one for the current change, and one for the previous change
4. if i do this again, same thing, new emails come, one for current change, and one for previous change.

very repeatable, and frustrating... any ideas?

thanks!
tony

Anthony Webb said...

@tom, do you know off hand if anyone ever fixed the issue with large files that you eluded to in this post? Ideally the "onAdd()" would only fire when the file was done being added.

Tom said...

@Anthony I don't have any pointers off hand to code that does that. I seem to remember that someone did this. The code is open source, so I would poke around the web for a better version.

Anonymous said...

This article solved a long standing issue of my code.

This line of code is all what i need..
Event.SetTimeOut(100)

Thank you!!

Anonymous said...

Hi Tom,

where i need to add this code

CFEvent.setCfcTimeOut()


Thanks,
Ash

Anonymous said...

Hi Tom,

where i need to add this code

CFEvent.setCfcTimeOut(100)