0

I have a CFC file which handles all of the emails I'm sending form an application (using Coldfusion8).

I was using CFINVOKE to call the respective function inside this CFC and passed a struct with all user data along like so:

<cfscript>  
var User.data = {};
    User.data.name = "John Doe";
    User.data.email = "john@doe.com";
    ...
</cfscript>     
// call mailer
<cfinvoke component="mailer_user" method="say_hi">
    <cfinvokeargument name="userData" value="#User.data#">
</cfinvoke>

And inside my mailer.cfc

<cffunction name="say_hi" access="public" output="false">
    <cfargument name="userData" type="struct" required="true" /> 
 ....

For some reason this now fails and I can only get it to work if I pass fields seperately as cfargument, which is a a pain, since I'm passing a lot of data.

Question: How can I get this to work using argumentCollection.

Even if I CFINVOKE like this:

 <cfinvoke component="mailer_user" argumentcollection="#User.data#" method="say_hi"></cfinvoke>

it still doesn't do a thing. I'm setting output flags right before the cfinvoke and after, as well as inside the "say_hi" function going in and out. I'm only getting the flag before CFINVOKE.

Side note: This is all done through AJAX and I'm only getting back success="false" if my CFC has an error somewhere. I only work remotely on the system, so I can't set AJAX debugging in CFADMIN

James A Mohler
  • 11,060
  • 15
  • 46
  • 72
frequent
  • 27,643
  • 59
  • 181
  • 333
  • What's the error you're getting if you pass data in using argumentCollection? Also, if you're using cfscript, why aren't you using oMailer = createObject("component","mailer_user"); oMailer.say_hi(argumentcollection=user.data); – Stephen Moretti Jul 18 '12 at 07:54
  • I'm not using cfscript, because I didn't know the syntax :-) (2nd month Coldfusion). I'm not getting any error, because AJAX just reports "success" or "fail"... I'm still wondering if there is a way to turn on some kind of error reporting because this guessing around sure eats up time. – frequent Jul 18 '12 at 07:59
  • ColdFusion server has a huge quantity of debugging options. Take a look in the administrator under debugging and logging. Bear in mind that turning on debugging will add stuff to the bottom of all pages including ajax results unless you tell it otherwise using cfsetting. Thing is, if it isn't throwing an error, then none of that will help you. You need to use traditional debugging with cfdump, cfabort, cflog and so on to help. – Stephen Moretti Jul 18 '12 at 08:07

4 Answers4

3

As I typed the comment above it occurred to me what the problem is likely to be.

You are passing in a structure to your function. You pass User.data which has name,email,blah,etc as keys in that structure. Those keys need to match the arguments in your function

<cffunction name="say_hi" access="public" output="false">
    <cfargument name="name" type="struct" required="true" /> 
    <cfargument name="email" type="struct" required="true" /> 
    <cfargument name="blah" type="struct" required="true" /> 
    <cfargument name="etc" type="struct" required="true" /> 

If you want to pass in the structure as a argument, you would need to have a user.userData as your structure of user data and your function should be

<cffunction name="say_hi" access="public" output="false">
    <cfargument name="userData" type="struct" required="true" /> 

When you pass the collection as argumentCollection you should do argumentCollection="#user#", so that the userData part matches your cfargument in the function.

Clear as mud?

Stephen Moretti
  • 2,442
  • 1
  • 18
  • 29
  • trying to wipe the mud away from my eyes... :-) – frequent Jul 18 '12 at 08:05
  • hm. actually I'm having USER = {}; as my structure. USER has USER.success, USER.fail and USER.Userdata as... objects/structs? I always reference USER.Userdata.name, USER.Userdata.email throughout my script and this is working fine. I just can't pass this thing into the mailer CFC anymore... Actually I'm now doing as you propose first with the mailer-calls, which only require a few fields, but now I have one with 25 fields... so I'm just reluctaned to pass them one by one when it was working fine before. – frequent Jul 18 '12 at 08:08
  • well if it was working fine before then something has changed in your function that is stopping it from working. As Henry says the syntax is ok. Stick a dump and abort in after your cfarguments of local if you're on cf9+ or arguments if you are on cf8. Make sure you are getting what you think you should. – Stephen Moretti Jul 18 '12 at 08:14
  • .... I just found it.... In the last email template I added, I had a variable ##tx_something# (no smiley for pulling hair out, is there...). I just commented out the whole CFC and checked for the message by message, last message, last textblock. – frequent Jul 18 '12 at 08:26
  • I still wonder why the whole CFC fails, if this message (function) isn't called though – frequent Jul 18 '12 at 08:27
  • You'll be getting a "compile" error. It won't even get as far as calling the function. Couple of things - run your dev server from a command window, so you can see what is going on server side when you're calling via web services. I've said this before, but try your components and methods from a simple html/cfml page before getting involved in ajax calls and the like. – Stephen Moretti Jul 18 '12 at 09:06
  • I had to jump right into this project with zero Coldfusion/MySQL experience. If I would have to do it again, I would set it up differently, but for this thing, I'm too far down the road and I had to work with a lot of existing stuff I inherited, so I'm more or less trying to fiddle my way through what I have while learning how not to do things next time I take on such an ... endavour – frequent Jul 18 '12 at 09:11
2

I think you should stay in cfscript style by writing

// call mailer
mailUser = createObject("component", "mailer_user");    // or new mailer_user(); for CF9+
mailUser.say_hi(User.data);

That should work, if it doesn't, it's somewhere else in your code. Try looking at the error log.

Henry
  • 32,689
  • 19
  • 120
  • 221
  • can I do this with CFINVOKE, too? Don't want to createObjects if I can avoid – frequent Jul 18 '12 at 07:57
  • why do you prefer cfinvoke? cfinvoke also creates the object before it invokes the method. Anyway, ya, what you had in the question is the correct syntax. If it's failing, it's not because of that line. – Henry Jul 18 '12 at 08:07
  • I always read cfobject is bad in Coldfusion8 and I should use cfinvoke. Also this is for a single email message, which does not get called that often, so I thought CFINVOKE is better, because once the email is gone, the CFINVOke is discarded and my server stays "clean". Correct me if I'm wrong here, please. – frequent Jul 18 '12 at 08:10
  • you're wrong. cfinvoke on a component is not any better than cfobject or createObject. – Henry Jul 18 '12 at 08:49
  • 1
    @frequent what about that link? I doubt the cfinvoke would `discard` the instance immediately. It just doesn't return a reference to you to keep. The instantiated object will have to wait until the request finishes and wait for jre's garbage collection, just like cfobject / createObject. – Henry Jul 18 '12 at 09:02
  • 3
    If you are making a single call to a component in a request, then cfinvoke is fine. If you are making multiple calls to methods in a component, then cfinvoke is bad, because it cannot be reused and instantiates every time. createobject is no better or worse than cfinvoke in the single call stakes, but in the multiple call situation its much better because an object is instantiated and kept in a variable for the length of the request and can be reused. Both are discarded at the end of the request, unless cached. – Stephen Moretti Jul 18 '12 at 09:09
1

You should map the variable to the data you pass, then no problem sending a struct. Do it this way

<cfset objMailer = createObject("component","mailer_user") />

<cfset objMailer.say_hi(userData:user.data)/>

This works even in CF7.

Sanjeev
  • 11
  • 1
  • yes, but I'm more onto CFINVOKE at the moment, so I'm not "creating any objects". I posted below, there was a typo in my mailer.cfc, which I did not see, because I'm of the system working solely on AJAX and me not being able to AJAX debug in CFAdmin. So I'm just getting "AJAX failed". I had a cfprocessingdirective mail text, where one variable had ##some_text#, which caused the whole cfc to break. Anyway. Thanks for the suggestion. – frequent Jul 19 '12 at 07:37
0

Ok. There was a typo inside my mailer CFC, where I had a variable with "##". As is was inside my email text it went unnoticed...

So you can pass a struct allright using this:

<cfinvoke component="mailer_user" method="say_hi">
    <cfinvokeargument name="userData" value="#User.userdata#">
</cfinvoke>

and grab it inside your called function like so:

<cffunction name="say_hi" access="public" output="false" hint=""> 
    <cfargument name="userData" type="struct" required="true" hint="user data  passed" /> 
    <cfscript>  
        var internalInfo = "";
        var User = {};
        User.userdata = userData;                   
    </cfscript> 
    ...

Maybe someone else can use the snippet.

frequent
  • 27,643
  • 59
  • 181
  • 333