8 Replies Latest reply on Oct 10, 2006 1:57 PM by Peter Farland

    Remote Object to CFC and back

    GeorgeWS Level 1
      I want to have in the url test.cfm?SupplierID=3

      The file should send the variable SupplierID to a CFC and the CFC send the data to the flex app. this is basicaly what I have for the RO (there is a grid that gets filled in from the RO)

      <mx:RemoteObject
      id="qResult"
      destination="ColdFusion"
      source="invbl"
      showBusyCursor="true" >

      <mx:method name="Inventory" result="handleQueryResult(event)" fault="Alert.show(event.fault.message)"/>
      <mx:method name="SupplierID">
      <mx:arguments>
      <supplierid>
      {Application.application.parameters.SupplierID}
      </supplierid>
      </mx:arguments>
      </mx:method>
      </mx:RemoteObject>

      I know the Application.application.parameters.SupplierID is good because I have another part of my app that sends that to another page where it gets the variable "3" just fine.

      In my sample above Im not sure if thats how to make the request.

      my CFC looks like this:

      <cfcomponent name="Inventory">
      <cffunction name="Inventory" access="remote" returnType="query" output="false">
      <cfargument name="supplierid" required="no">

      <CFQUERY NAME="Inventory" DATASOURCE="COREDATA">
      SELECT PNUM5W, PDES5W, SDIVDE, ISCF3W, DIVN5W, COMC5W, COMCDE, PGMJ5W, PGMJDE,
      INV_51, ORD_51, SUBSTRING(DAT_51,4,2) + '/' + SUBSTRING(DAT_51,6,2) AS DAT_51, INT_51,
      INV_61, ORD_61, SUBSTRING(DAT_61,4,2) + '/' + SUBSTRING(DAT_61,6,2) AS DAT_61, INT_61,
      INV_71, ORD_71, SUBSTRING(DAT_71,4,2) + '/' + SUBSTRING(DAT_71,6,2) AS DAT_71, INT_71,
      INV_81, ORD_81, SUBSTRING(DAT_81,4,2) + '/' + SUBSTRING(DAT_81,6,2) AS DAT_81, INT_81
      FROM InvBL
      <cfif structKeyExists(arguments, "supplierid")>
      WHERE PGMJ5W = <cfqueryparam value="#arguments.supplierid#" cfsqltype="cf_sql_varchar" />
      </cfif>
      ORDER BY PDES5W, SDIVDE, PNUM5W
      </CFQUERY>

      <cfreturn Inventory>
      </cffunction>
      </cfcomponent>

      If I hard code a 3 in the place of the "arguments.supplierid" the app works fine. so IM thinking that the CFC never gets the variable. Can anyone tell me how to do this?

      Thanks
      George

        • 1. Re: Remote Object to CFC and back
          Peter Farland
          Can you show me the code that actually calls your RemoteObject? Do you just call send()?

          Also, I think your MXML for the method of your RemoteObject should be <mx:method name="Inventory"> as this is the name of the CFC function you're looking to call.
          • 2. Re: Remote Object to CFC and back
            GeorgeWS Level 1
            So far its kinda like this im leaving some script out just to simplify.

            <mx:Application xmlns:mx=" http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="initVars()" >

            <mx:Script>

            [Bindable]
            public var myData:ArrayCollection;

            [Bindable]
            public var SupplierID:String;

            private function initVars() : void {
            SupplierID = Application.application.parameters.SupplierID;
            }
            </mx:Script>

            <mx:RemoteObject
            id="qResult"
            destination="ColdFusion"
            source="invbl"
            showBusyCursor="true" >

            <mx:method name="Inventory" result="handleQueryResult(event)" fault="Alert.show(event.fault.message)"/>
            <mx:method name="SupplierID">
            <mx:arguments>
            <supplierid>
            {Application.application.parameters.SupplierID}
            </supplierid>
            </mx:arguments>
            </mx:method>
            </mx:RemoteObject>


            There is a panel and grid and stuff here...

            My CFC is like this:

            <cfcomponent name="Inventory">
            <cffunction name="Inventory" access="remote" returnType="query" output="false">
            <cfargument name="supplierid" required="no">

            <CFQUERY NAME="Inventory" DATASOURCE="MyData">
            SELECT PNUM5W, PDES5W, SDIVDE, ISCF3W, DIVN5W, COMC5W, COMCDE, PGMJ5W, PGMJDE,
            INV_51, ORD_51, SUBSTRING(DAT_51,4,2) + '/' + SUBSTRING(DAT_51,6,2) AS DAT_51, INT_51,
            INV_61, ORD_61, SUBSTRING(DAT_61,4,2) + '/' + SUBSTRING(DAT_61,6,2) AS DAT_61, INT_61,
            INV_71, ORD_71, SUBSTRING(DAT_71,4,2) + '/' + SUBSTRING(DAT_71,6,2) AS DAT_71, INT_71,
            INV_81, ORD_81, SUBSTRING(DAT_81,4,2) + '/' + SUBSTRING(DAT_81,6,2) AS DAT_81, INT_81
            FROM InvBL
            <cfif structKeyExists(arguments, "supplierid")>
            WHERE PGMJ5W = <cfqueryparam value="#arguments.supplierid#" cfsqltype="cf_sql_varchar" />
            </cfif>
            ORDER BY PDES5W, SDIVDE, PNUM5W
            </CFQUERY>

            <cfreturn Inventory>
            </cffunction>
            </cfcomponent>

            Thanks for looking
            George
            • 3. Re: Remote Object to CFC and back
              Peter Farland Level 3
              Sorry, I wasn't clear in my last post. Your MXML tag for RemoteObject is incorrect... you have two <mx:method> tags, but you should only have one:

              <mx:RemoteObject
              id="qResult"
              destination="ColdFusion"
              source="invbl"
              showBusyCursor="true" >

              <mx:method name="Inventory" result="handleQueryResult(event)" fault="Alert.show(event.fault.message)">
              <mx:arguments>
              <supplierid>
              {Application.application.parameters.SupplierID}
              </supplierid>
              </mx:arguments>
              </mx:method>
              </mx:RemoteObject>
              • 4. Re: Remote Object to CFC and back
                GeorgeWS Level 1
                Thanks Peter,
                I did take that out yesterday. So im calling the correct one, inventory. BUT....
                that did not help either. I did spend the whole day on this and still no progress. I must be the dumbest
                Thanks for hangen in there with me. I did read a post about sending 2 variables one with a null or something. I tried that and abunch of other stuff to no avail. I also have read a bunch a posts claiming its a bug. If so this makes Flex useless for me. CF Flash Forms is so easy compaird to this. I want this to work so bad. Lots of big giant companies are relying on me to pull through. If I can show them this works maybe they would consider Flex.

                George
                • 5. Remote Object to CFC and back
                  Peter Farland Level 3
                  quote:

                  Originally posted by: GeorgeWS
                  I did read a post about sending 2 variables one with a null or something. I tried that and abunch of other stuff to no avail. I also have read a bunch a posts claiming its a bug.


                  What you're trying to do is simple and in general it is supported, something just must be confused in the code - we'll have to work out what that is.

                  Note that post you mention about sending 2 variables - this technique in Flash Remoting was to avoid an issue with CFC methods as you have to help it distinguish that you're not sending named arguments but one argument that is a single complex object. Named arguments are like a struct of key-value pairs... and an ActionScript Object does represent such a struct to CF. This method of representing arguments would be unfamiliar to a Java or AS developer as functions typically take ordered arguments. Anyway, named argument confusion arises if you're sending a single ActionScript Object to a CFC method - the Flash Remoting adapter in ColdFusion can't get access to the real API of your CFC method (due to certain internal limitations) to check the signature or number of arguments so it has to assume that a single ActionScript Object is a set of named arguments rather than a single parameter. If you send a second argument after the Object, it knows it's not a set of named arguments but instead its a list of plain old ordered arguments. In order to send two arguments, however, your CFC method signature needs to have at least two arguments defined (obviously)... the first one would be of type struct to handle the AS Object argument and the second can be anything... you can always just ignore the second argument and not use it in your function.

                  The reason you may be hitting this problem is that you're using MXML based syntax for arguments to take advantage of automatic binding code. If you do choose this route, you need to understand just what the MXML compiler is generating for your code:

                  <mx:method name="Inventory" result="handleQueryResult(event)" fault="Alert.show(event.fault.message)">
                  <mx:arguments>
                  <supplierid>
                  {Application.application.parameters.SupplierID}
                  </supplierid>
                  </mx:arguments>
                  </mx:method>

                  Note that the child of <mx:arguments> is seen just like an <mx:Model>... a declarative view of an object graph. The <supplierid> is seen as a property name, and the value is a binding expression (in your case evaluating to the value 3). This is equivalent to the following ActionScript:

                  arguments = new Object();
                  arguments["supplierid"] = 3;

                  So, you may indeed be sending an Object instead of just the number 3?

                  You could check this in you CFC by looking whether "#arguments.supplierid.supplierid#" is defined.

                  Whenever you're dealing with data communications you should be aware of the ways to view the data being transmitted as without it it makes debugging very difficult. Do you know about the debug flashplayer's ability to trace out statements to a flashlog.txt file? Are you familiar with the <mx:TraceTarget level="0" /> technique in Flex? Do you know about the ways of turning on debug level logging for either Flash Remoting (setting logging level to "debug" in gateway-config.xml) or Flex Data Services (setting logging level to "debug" in services-config.xml) and looking at the server logs (or the console if you started the app server on the command line)?

                  • 6. Re: Remote Object to CFC and back
                    GeorgeWS Level 1
                    Pete,
                    I look at the CFC and replaced my #arguments.supplierid# with #arguments.supplierid.supplierid# and I get an error saying undefined. I dont know much about the debugger either, mainly because it requires setup and the CF plugin for communication needed a very painful poorly documented setup and all this seems so mickey mouse. Pretty much I want to run the debugger and have it go through the progam line by line or something and show me whats set and stuff but I dont know how. Im stumped without a sample. Im confused about a bunch of stuff. When you say MXML compiler what do you mean? I dont complie I just export. Where is the compile button? I have never heard of the <mx:TraceTarget level"0"/> . Pretty much I know nothing, it seems. I just want to send one variable to my CFC. My remoteObject looks like other code samples and my CFC looks like the samples. It just does not work.
                    • 7. Re: Remote Object to CFC and back
                      Peter Farland Level 3
                      There should have been numerous postings on forums about setting up debug level logging for using Flash Remoting or Flex requests with ColdFusion, but if you're not comfortable with this another approach might be to redirect CFDUMP output (or some equivalent) for the various scopes like variables/arguments/flash etc... to some text file log using CFFILE to inspect what is in them.

                      Also, have you tried short hand syntax for the argument like #supplierid#? Or what about the #flash.supplierid# (not sure if that is available via CFC but only CFM)?

                      If you are stuck then can you email me your flex code and cfc to pfarland@adobe.com?
                      • 8. Re: Remote Object to CFC and back
                        Peter Farland Level 3
                        I got your sample to work.

                        A few things to mention after looking at the full version of your code - note that to call a RemoteObject method that has predefined MXML arguments then you would call it like this:

                        qResult.Inventory.send();

                        If you wanted to programmatically call it with arguments from ActionScript, you'd call it like this:

                        qResult.Inventory(SupplierId, BrandId);

                        But the real problem was that you're calling the RemoteObject method in the initialize property of a data grid - not only is this unconventional, it won't work as you must wait until later to access the Application.application scope. There is a more complex set of reasons I won't go into here, but in general when working with data or programmatic interactivity I suggest waiting for creationComplete on the top level Application to be fired before making any requests.