CF says I'm trying to dereference a scalar, but I'm not.

Posted on December 6, 2007

At least I think I’m not. It happens in a DirectoryWatcher (Event Gateway) method. Can someone take a look at this and let me know what you think.

We’re using CF 7.0.2 Enterprise, multi-instance with JVM 1.4.2_12 (b03) on Windows 2003 server.

The Problem

Basically, I’m creating an XML file from form data and sending it to a bunch of CF servers via CFFTP. This part works fine. I have an Event Gateway OutageWatcher monitoring the FTP folder for changes.

OutageWatcher.cfc

<cfcomponent output="false" extends="path.to.XmlTools">

  <cffunction name="onChange" access="public" output="false" returntype="boolean" hint="Fires off when a file changes.">

    <cfargument name="cfEvent" type="struct" />

    <cfset var theFile = cfEvent.data.filename />

    <cflog file="OutageWatcher" application="true" type="information" text="File changed: #theFile#" />

    <cfif listLast( theFile, "\" ) is "outage.xml">

      <cflog file="OutageWatcher" application="true" type="information" text="#theFile# has been updated." />

      <cftry>
        <cflock scope="Server" type="exclusive" timeout="2">
          <cfset server.outage = structNew() />
          <cfset structAppend( server.outage, duplicate( loadXmlConfig( theFile ).config.outage ) ) />
        </cflock>
        <cfcatch type="any">
          <cflog file="OutageWatcher" application="true" type="error" text="server.outage has not been updated." />
          <cfreturn false />
        </cfcatch>
      </cftry>

      <cflog file="OutageWatcher" application="true" type="information" text="server.outage has been updated." />

    </cfif>

    <cfreturn true />

  </cffunction>

</cfcomponent>

When the file “outage.xml” is changed, onUpdate() fires off. loadXmlConfig() (inherited from XmlTools.cfc) just reads the XML file and parses it into a struct. Afterwards, the data is copied into a server scoped variable, server.outage. This is all based on some code that Joe Rinehart posted.

This all works. It works perfectly. But I keep getting this error in exception.log:

"Error","Thread-10","12/06/07","12:40:55",,"Error invoking CFC for gateway OutageWatcher: You have attempted to dereference a scalar variable of type class java.lang.String as a structure with members. "
coldfusion.runtime.ScopeCastException: You have attempted to dereference a scalar variable of type class java.lang.String as a structure with members.
  at coldfusion.runtime.Cast._Map(Cast.java:898)
  at coldfusion.eventgateway.EventRequestHandler.invokeCFC(EventRequestHandler.java:169)
  at coldfusion.eventgateway.EventRequestHandler.processRequest(EventRequestHandler.java:102)
  at coldfusion.eventgateway.EventRequestDispatcher$Task.run(EventRequestDispatcher.java:121)
  at coldfusion.util.SimpleWorkerThread.run(SimpleThreadPool.java:214)

And this error in eventgateway.log:

"Error","Thread-10","12/06/07","12:40:55",,"Error invoking CFC for gateway OutageWatcher: You have attempted to dereference a scalar variable of type class java.lang.String as a structure with members. "

Debugging

So I fired up the latest version of Fusion Debug to see what was happening under the hood.

I set a breakpoint just inside the CFLOCK to see if the error was really being thrown from the Event Gateway or from the inherited method.

Debugging breakpoint

<cfset server.outage = structNew() />

The debugger stepped through the code, moved into the other CFC and ran through loadXmlConfig() just fine. It then returned to the onChange() method without an error.

I watched the log files and they updated as expected.

It never went into the CFCATCH block. So there was no error in that section of code.

The variable server.outage was updated correctly.

The last CFLOG ran just fine.

The final CFRETURN ran correctly.

It highlighted the end of the function.

and them BAM! Error

WTF?

If I remove the try/catch tags, of course, there’s no error. But that’s like the guy who goes to the doctor and says, “hey doc, it hurts when I do this” motions and the doctor replies, “then don’t do that”.

Any ideas?

Update: Found the problem

A coworker dropped by and I told him the scenario. I’d already tested each individual part of the process outside of the Gateway, so he suggested just changing the returntype to string to see what would happen.

Same error.

I changed the returntype back to boolean and commented out everything but

<cfreturn true />

Same error.

We had the same thought as Techie Jim (before I saw your comment, but you had the right idea [#2]).

We checked the Livedocs entry again and noticed something “odd” with the example.

<cffunction name="onChange" output="no">

There's no returntype.

I removed the returntype, as well as the two CFRETURNs. I updated the file in the directory it was watching and voilà ! No more error.

Thanks everyone.

About the Author
Adrian J. Moreno

Adrian is an enterprise solution architect and full stack developer. Which stack depends on which system is on fire at the time. More information