Unable to persist CFC to App scope if invoked by Webservice call (With workaround)

I have come across the following issue when attempting to persist a CFC to the Coldfusion Application scope, when the the CFC method had been invoked remotely.

If I take the following cfc:

app_persit.cfc

<cfcomponent output="true">
   <cffunction name="init" output="true">
      <cfif not isdefined("application.persistedobject")>
         <cfset _initialiseObject()>
         <cfset variables.persitedvalue = 54321>
      <cfelse>
         <cfset variables.persitedvalue = 0>
      </cfif>
      
      <cfreturn application.persistedobject>
   </cffunction>
   
   <cffunction name="remotetest" output="false" access="remote" returntype="numeric">
      <cfset var localObject = init()>
      <cfreturn localObject.returnPersistedValue()>
   </cffunction>

   <cffunction name="_initialiseObject" output="true">
      <cfset variables.persitedvalue = 12345>
      <cfset application.persistedobject = this>
   </cffunction>
   
   <cffunction name="returnPersistedValue" output="false" returntype="numeric">
      <cfreturn variables.persitedvalue>
   </cffunction>
</cfcomponent>

and call it with the following CFML code:

test_app_persit.cfm

<cfset persistedobject_ref = createobject("component","app_persist")>
<cfset x = persistedobject_ref.remotetest()>
<cfdump var="#x#">

The object would get created, and persisted to application scope correctly - with all subsequent calls to the remotetest() function using the object which had been persisted to Application scope.

If I then try to call this method as a web service (after first clearing the application scope) as follows:

<cfset persistedobject_ref = createobject("webservice","http://localhost/cf7/test/cfcs/app_persist.cfc?wsdl")>
<cfset x = persistedobject_ref.remotetest()>
<cfdump var="#x#">

The first time I execute the code, it runs as expected.

On all subsequent requests, I would get the following error:

Could not perform web service invocation "remotetest".
Here is the fault returned when invoking the web service operation:

AxisFault
faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException
faultSubcode:
faultString: coldfusion.xml.rpc.CFCInvocationException:
   [java.lang.NullPointerException : null]
faultActor:
faultNode:
faultDetail:
   {http://xml.apache.org/axis/}stackTrace:coldfusion.xml.rpc.CFCInvocationException: [java.lang.NullPointerException : null]
   at coldfusion.xml.rpc.CFComponentSkeleton.__createCFCInvocationException(CFComponentSkeleton.java:714)
   at coldfusion.xml.rpc.CFComponentSkeleton.__invoke(CFComponentSkeleton.java:660)
   at cf7.test.cfcs.app_persist.remotetest(C:\sites\cf7\test\cfcs\app_persist.cfc)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:324)
   at org.apache.axis.providers.java.RPCProvider.invokeMethod(RPCProvider.java:388)
   at org.apac...

On further investigation, it appears that although application.persistedobject was defined, it was a null reference - i.e. the object to which the variable had pointed no longer exists.

So it appears that it is not possible to persist a CFC to the application scope a method is executed remotely. (Is this a bug? - I expected the same behaviour from a remote invocation as from a local invocation...)

As a work around (and probably better practice anyway) I created the following wrapper CFC:

app_persist_wrapper.cfc

<cfcomponent output="true">
   <cffunction name="remotetest" output="true" access="remote" returntype="numeric">
      <cfset var localObject = "">
      <cfset var persistedobject_ref = createobject("component","app_persist")>
      <cfset localObject = persistedobject_ref.init()>
      <cfreturn localObject.returnPersistedValue()>
   </cffunction>
</cfcomponent>

When I invoked this as follows:

<cfset persistedobject_ref = createobject("webservice","http://localhost/cf7/test/cfcs/app_persist.cfc?wsdl")>
<cfset x = persistedobject_ref.remotetest()>
<cfdump var="#x#">

This works correctly - the original object is persisted to application scope as intended, and retrieved from there on subsequent requests.

(Took me over a day to figure out what was happening here as part of testing a much more complex application - hopefully this will save someone else some time :)

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
Arowolo M.A's Gravatar thats cool
well i've not tried persisting my WS before.
i think i'll try this out
# Posted By Arowolo M.A | 22/04/08 09:54
BlogCFC was created by Raymond Camden. This blog is running version 5.5.1, hosted by TalkWebSolutions.