+ Start a Discussion
Andy Freeston_LarterAndy Freeston_Larter 

Parameter mismatch bug with WebServices and Flex

I have an Apex class that exposes a function through the WebServices interface. The function has a number of parameters that are based on the same type. When I call this function from Flex, the data that I am passing is being put into the wrong parameters. I am not sure if this is a bug in Salesforce, the Force.com toolkit, or Flex.


My flex code passes 2 Id values via the deletedEntitiesIds parameter. The other three collections are empty.


var deletedTeamMembersIds:Array = new Array; var deletedEntitiesIds:Array = new Array; var deletedTeamIntimacyIds:Array = new Array; var deletedRelationshipsIds:Array = new Array; deletedEntitiesIds.push( id1 ); deletedEntitiesIds.push( id2 ); var args:Array = [ new Parameter( "OpportunityId", _opportunityId ), new Parameter( "instanceNumber ", _instanceNumber ), new Parameter( "deletedIntimacies", deletedTeamIntimacyIds, true ), new Parameter( "deletedRelationships", deletedRelationshipsIds, true ), new Parameter( "deletedEntities", deletedEntitiesIds, true ), new Parameter( "deletedTeamMembers", deletedTeamMembersIds, true ) ]; _force.execute( "MSO_OrgChart_WebService", "updateOrgChart_Delete" , args, new AsyncResponder(SaveToSalesforce_DeleteHandler, SaveToSalesforceFaultHandler), "SalesMethods" );



The Apex function just writes the collections into the debug log:



global with sharing class MSO_OrgChart_WebService { WebService static UpdateResult updateOrgChart_Delete( Id OpportunityId, Integer instanceNumber, List<Id> deletedIntimacies, List<Id> deletedRelationships, List<Id> deletedEntities, List<Id> deletedTeamMembers ) { System.debug( deletedIntimacies ); System.debug( deletedRelationships ); System.debug( deletedEntities ); System.debug( deletedTeamMembers ); } }



As the debug log shows, the Id values are now in the deletedIntimacies collection rather than in the deletedEntities collection.


20091110211500.108:Class.SalesMethods.MSO_OrgChart_WebService.updateOrgChart_Delete: line 379, column 1: (a0X80000001v3n5EAA, a0X80000001v3omEAA) 20091110211500.108:Class.SalesMethods.MSO_OrgChart_WebService.updateOrgChart_Delete: line 380, column 1: () 20091110211500.108:Class.SalesMethods.MSO_OrgChart_WebService.updateOrgChart_Delete: line 381, column 1: () 20091110211500.108:Class.SalesMethods.MSO_OrgChart_WebService.updateOrgChart_Delete: line 382, column 1: ()




Am I doing something wrong or is this another Force/Flex bug?



Many thanks,



Andy Freeston_LarterAndy Freeston_Larter

After doing more testing I have found that this is not an isolated incident. I have other function calls with different data types and numbers of parameters that also show the same symptoms.


It seems this bug affects all WebService calls where there are two or more parameters that take the same datatype. This function is also failing:

WebService static UpdateResult updateOrgChart_Entities( Id OpportunityId, Integer instanceNumber, List<UpdateEntityData> newEntities, List<UpdateEntityData> changedEntities ) { System.debug( newEntities ); System.debug( changedEntities ); }



The only work around that I have is to replace the function parameters with a class, as class-based values do seem to be passed correctly.




I am having the same issue, and I created a class that contain's all the parameters to the webservice method and tried to pass it in. But it doesn't seem to work.  Would you be able to give me a sample of how you are doing this and what I should watch out for since you have done this already.  Thank you very much



Andy Freeston_LarterAndy Freeston_Larter



I have confirmed that this is a bug and I'm working with the SF support to try and get it fixed. It only seems to affect methods that have multiple parameters that take the same data type, possibly only when the parameters are collections.


To work around the bug, you need to change your Apex method to accept a class, like this:


global class ParamsForTest2 { WebService List<Id> paramA; WebService List<Id> moreData; } WebService static void test2( ParamsForTest2 params ) { // Do something with params.paramA // Do something with params.moreData }



You then need to change your Flex code to build the class and pass it as a parameter, like this:



var listOne:Array = new Array; listOne.push( "0068000000OPGlbAAH" ); var listTwo:Array = new Array; listTwo.push( "0068000000RCFOF" ); // Build the class. Set the names to match the names in the Apex class var params:Object = { paramA:listOne, moreData:listTwo }; // Build the arguments for the call. Name must match parameter name in Apex class var args:Array = [ new Parameter( "params", new ObjectProxy(params) ), ]; // Call the method _force.execute( "ApexClassName", "test2" , args, new AsyncResponder(SuccessHandler, FaultHandler), "Namespace" );




If you still have problems, post your code and I'll take a look.


- Andy




I'm trying your code, but I really don't know how to make it work with my use case in Flex,


Taking your example the Salesforce side should look like this adding a List<> of complex types as the parameter of the webservice method:




global class ParamsForTest2{ WebService List<Id> paramA; WebService List<Id> moreData;}WebService static void test2( List<ParamsForTest2> params ){ // Do something with params.paramA // Do something with params.moreData}


Can you Post how should look the Flex side passing a List of complex types instead of only one instance ?,


Thanks in advance. 


Andy Freeston_LarterAndy Freeston_Larter



Assuming you just wanted to pass two lists of ids, your Apex method should look like:

WebService static void test2( ParamsForTest2 params ) { // Do something with params.paramA // Do something with params.moreData }



The corresponding Flex code should look something like:

{ var arrayParam:Array = new Array; // Corresponds to List<Id> paramA // Store Ids in arrayParam var arrayMore:Array = new Array; // Corresponds to List<Id> moreData // Store Ids in arrayMore var params:Object = { paramA:arrayParam, moreData:arrayMore }; var args:Array = [ new Parameter( "params", new ObjectProxy(params) ) ]; _force.execute( "YourWebServiceClass", "test2" , args, new AsyncResponder(SuccessHandler, FaultHandler), "YourNamespace" ); }





Thanks for your response, that way works perfectly for me, only passing one complex type that handles multiple fields that might contain collections,


Allow me to explain myself more accurately my use case, 


Salesforce Side: 


global class MySingleComplexType


    WebService    String   SingleParamA;

    WebService    Integer SingleParamB;



WebService static void TestingFlexMethod( List<MySingleComplexType> params )


  //Iterate received params collection of type <MySingleComplexType>

    // Do something with current MySingleComplexType




 What I'm trying is passing from Flex a collection of "MySingleComplexType" for being processed by "TestingFlexMethod", 


Using your scenario, should I then have to declare ?


global class MySingleComplexTypeCollection


    WebService    List<MySingleComplexType> CollectionParamA;

WebService static void TestingFlexMethod( MySingleComplexTypeCollection params )


  //Iterate received params 

    // Do something with current MySingleComplexType



 Thanks in advance.






Well it works now !,


Only I had to do was some little modifications to your example, thanks for this great help,



var prodOne : Object = {SingleParamA:'strValue', SingleParamB:5};

var prodTwo : Object = {SingleParamA:'strValue1', SingleParamB:6};                              


var klak0 : ObjectProxy = new ObjectProxy(prodOne);

var klak1 : ObjectProxy = new ObjectProxy(prodTwo);


var arrData : Array = new Array();




var args:Array = [new Parameter("params", arrData)]; 




Message Edited by magdielhf on 02-12-2010 02:42 PM