function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
WilmerWilmer 

Looking for a sample of how to consume a SFDC web service by using Scripting Toolkit

Hi everybody,

I need to consume a Salesforce web service (Apex Class) by using Scripting Toolkit. I already have the WSDL of the web service and it's being a long time I don't work with this kind of things so sincerely I´m not sure about how to do that. Could anybody provide me an example of this? I'd appreciate any help.

Thanks.
Best Answer chosen by Admin (Salesforce Developers) 
ArtabusArtabus
The Scripting ToolKit has a similar behaviour as the Ajax Toolkit. You should call your webservice the same way you would do it in an scontrol.
I have just uploaded a new version (0.4.8) of the ToolKit which is now API 13.0 compliant, and allows you to call Apex webservices.
A call to the WebService should be only 3 lines of code in your "myscript.js" file :
 
result = sforce.apex.execute('MyWebServiceClass' ,'MyMethod',{theParam:"Something", secondParam:"Something else"});
WScript.echo(result);
ToolKit.Quit();
 
And here is the Apex webservice code :
global class MyWebServiceClass {
    webService static String MyMethod(String theParam, String secondParam) {
        return 'Hello '+theParam;
    }
}
I hop this helps,

All Answers

ArtabusArtabus
The Scripting ToolKit has a similar behaviour as the Ajax Toolkit. You should call your webservice the same way you would do it in an scontrol.
I have just uploaded a new version (0.4.8) of the ToolKit which is now API 13.0 compliant, and allows you to call Apex webservices.
A call to the WebService should be only 3 lines of code in your "myscript.js" file :
 
result = sforce.apex.execute('MyWebServiceClass' ,'MyMethod',{theParam:"Something", secondParam:"Something else"});
WScript.echo(result);
ToolKit.Quit();
 
And here is the Apex webservice code :
global class MyWebServiceClass {
    webService static String MyMethod(String theParam, String secondParam) {
        return 'Hello '+theParam;
    }
}
I hop this helps,
This was selected as the best answer
WilmerWilmer
Hi, Great news.

You saved my life. I´m gonna test it and let you know soon about its result.

Thanks again and God bless you.


WilmerWilmer
Hi artabus,

First of all, thanks for you cooperation in this case.

I´ve been trying to run it but seems something is missing 'cause I get the following message:

scriptingtoolkit.wsf(599, 10) msxml3.dll: The system cannot locate the resource specified.

My PC has Windows Vista. Could be that related to the error message? What could I do to fix it?

Thanks again.
WilmerWilmer
Hi Artabus,

I've been tracing the error and it seems to located at line 599 of the connection.js file where it says:

Code:
this.send = function (envelope, callback, async, timeout) {
        this.newConnection();
        if (async) {
            this.connection.onreadystatechange = this.httpConnectionCallback;
        }
        var holder = new sforce.internal.ConnectionHolder(this.connection, callback);
        sforce.internal._connections.push(holder);
        this.connection.open("POST", this.url, async);
        this.connection.setRequestHeader("Content-Type", "text/xml; charset=UTF-8");
        this.connection.setRequestHeader("SOAPAction", "\"\"");
        this.connection.setRequestHeader("Accept", "text/xml");
        this.connection.setRequestHeader("User-Agent", "SFAJAX 1.0");
        this.connection.send(envelope);
        if (async && typeof(timeout) !== "undefined") {
            this.setTimeoutOn(holder, timeout);
        }
        if (!async) {
            this.httpConnectionCallback();
        }
    };

 exactly at line 599 =  this.connection.send(envelope);

I hope this helps to find an answer. Thanks.

ArtabusArtabus
You are right, it was working only with the /server parameter. I have updated the wsf file, this should be ok now, please donwload it
WilmerWilmer
Hi Artabus,

Great, I've just tested it and work perfectly!!!!

Thanks and congratulations, you have a very useful tool and now, better.

Regards,

Wilmer
WilmerWilmer
Well, I downloaded but this time I got this error.

scriptingtoolkit.wsf(930, 10) JScript Runtime error : 'push' is null or not an object.

It's located at this function:
Code:
sforce.Apex.prototype.execute = function (pkg, method, args, callback, isArray) {
    pkg = pkg.replace(/\./g, "/");

    var sobjectNs = "http://soap.sforce.com/schemas/package/" + pkg;
    var nsmap = [{ns:sobjectNs, prefix:""}];

    if (!args) {
        throw "args not specified";
    }

    var params = [];
    for (var field in args) {
        var value = args[field];
        var arrayParam = value === null ? false : (value.push?true:false);
        var param = new sforce.internal.Parameter(field, value, arrayParam);
        params.push(param);
    }

    var isRealArray = true;

    if (isArray === false) {
        isRealArray = false;
    }

    return sforce.connection._invoke(method, params, isRealArray, callback, nsmap,
            sforce.connection.serverUrl.substr(0,sforce.connection.serverUrl.indexOf('/',10))+"/services/Soap/package/" + pkg, sobjectNs, sobjectNs);//changed
};

 At line 930.
var arrayParam = value === null ? false : (value.push?true:false);
                                                                    ========
Hope this helps.

ArtabusArtabus

This part of code is the same as the one written in the apex.js file (used for scontrols).

The error could be because of the parameters used when calling the execute() method.

Could you please provide the call you are trying to do (parameters used for the execute() call) ?

Thanks,

WilmerWilmer
Hi, these are the parameters I have:
Code:
function BulkProcessSTEP1(){
var Avance = '';
var maxUniqueId = sforce.apex.execute(
'BulkProcess_cls', 'ValidatingPatients_cls', {limitin:100, starting:startingNumber, strCountry:'Chile', strFarmacy:Farmacy},
function(result){
Avance = result;
var UniqueId = result[0];
recordProcessed = recordProcessed + (result[1]- 0) - 0;
if(result.length>1){
recordsOK = recordsOK + (result[2]- 0) - 0;
recordsFAIL = recordsFAIL + (result[3]- 0) - 0;
if(Farmacy=='')
Farmacy = result[4];
}
if(UniqueId == '0'){
divFASE1 = 'STEP 1... Validation of patients completed: Total Records: '+recordProcessed + '. Records OK: ' + recordsOK + '. Records Failure: ' +recordsFAIL;
divMessage1 = '';
WScript.echo(divFASE1);
startingNumber = '0';
TotalReg = recordProcessed;
TotalErrores = recordsFAIL;
TotalRegOK = TotalReg - TotalErrores;
recordProcessed = 0;
recordsOK = 0;
recordsFAIL = 0;
BulkProcessSTEP2();
}else{
divMessage1 = "STEP 1. Validating Patients...";
Avance = 'Record: ' + startingNumber + ' --> ' + UniqueId; // Report of progress.
Avance += '\nRecords processed: ' + recordProcessed + '. Records OK: ' + recordsOK + '. Records Failure: ' +recordsFAIL;
WScript.echo(divMessage1 + '\n' + Avance);
startingNumber = UniqueId; // Define next iteration
window.setTimeout("BulkProcessSTEP1()",90); // Loop again
}
}
);
}

 This way to call the Apex Class works fine in a scontrol.
 
ArtabusArtabus

I tried your code which I truncated a little bit and it is working fine :

Code:
var startingNumber=0;
var Farmacy="";
function BulkProcessSTEP1(){
      var Avance = '';
      var maxUniqueId = sforce.apex.execute(
       'BulkProcess_cls', 'ValidatingPatients_cls', {limitin:100, starting:startingNumber, strCountry:'Chile', strFarmacy:Farmacy},
       function(result){
  WScript.echo(result);
  ToolKit.Quit();
       }
      );
     }
BulkProcessSTEP1();


 
The webservice I used for the test :

Code:
global class BulkProcess_cls{
    webService static String ValidatingPatients_cls(Integer limitin, Integer starting, String strCountry, String strFarmacy) {
        return 'It is ok';
    }
}

 

ArtabusArtabus
I have found it ..

My previous code is working well because all variables are correctly initialised.
Just replace var Farmacy="";   with var Farmacy;
The variable will be undefined and produce that error.

Ensure all parameters are well defined, with valid (and perhaps not null) values



Message Edited by Artabus on 07-17-2008 12:26 AM
WilmerWilmer
Hi Artabus, (Thanks again)

Well, you were right, I wasn't passing any value in the Farmacy parameter. Now I run it and it's really strange because I get the expected response but then another error comes up showing the next message: ERROR: ........... [object Error]   (error message located at line 1005 into connection.js file)

And this is the reponse I print:
134839,2,0,2,MY FARMACY      (This is the response. An array with some important values into the process).


Now, as you saw, what I try to do is to call the same web service but this time the startingNumber will be set = 134839 in order to continue evaluating a huge table to avoid Apex limits. So I don´t understand why that error is shown in spite of the correct response?

I really appreciate your help in this.

Thanks,
Wilmer
ArtabusArtabus
I can reproduce your issue, by changing in my short sample above the line  var startingNumber=0; with the line var startingNumber=0.2;
You get exactly the same error at the same line, which is in fact
{faultcode:'soapenv:Client', faultstring:''0.2' is not a valid value for the type xsd:int', }
This means you still have an issue with the type of your variable.
If an integer is required, ensure that you are using parseInt(yourvariable) to use an integer value.
 
WilmerWilmer
Hi Artabus,

As usual you're right again.

I sincerely want to thank you for your help and support.

I checked the code and added the parseInt function to reset a integer-type variable after receiving the web service response and trying to call it again using the same variable, it was not necessary in a scontrol version but here it is. So now I tested it and work very well.

So, where can I promote this new feature of Scripting Toolkit? because it's a good and efficient solution to save hundreds of hours of coding to call Apex web services from an external tool in Salesforce.

Regards,

Wilmer