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
LosintikfosLosintikfos 

@Future

Hi Experts,


Do anyone know how to define methods that are defined as asynchronous,
that is, defined with the @future keyword? Simple sample will be highly appreciated.


B
Best Answer chosen by Admin (Salesforce Developers) 
jkucerajkucera

GV - you can't pass Sobjects as parameters into asynch methods.  From the annotations help:

 

"Methods with the future

annotation cannot take sObjects or objects as arguments. "

 

You can pass a list or set of ID's and then query for the objects inside the method. 

All Answers

ReidCarlbergReidCarlberg
There's some good examples over in the docs (where I stole the example below).

Code:
global class MyFutureClass {

  @future 
  static void myMethod(String a, Integer i) {
    System.debug('Method called with: ' + a + ' and ' + i);
    //do callout, other long running code
  }
}

The following snippet shows how to specify that a method executes a callout:

  @future (callout=true)
  public static void doCalloutFromFuture() {
   //Add code to perform callout
}

 

David VPDavid VP
Since you know about asynchronous calls and the @future annotation I assume that you've seen what's in the Apex Language Reference ?
There are a couple of examples in there :

Code:
global class MyFutureClass {

  @future 
  static void myMethod(String a, Integer i) {
    System.debug('Method called with: ' + a + ' and ' + i);
    //do callout, other long running code
  }
}




David



LosintikfosLosintikfos
I have just realised the @future anotation donot support return type method only void type methods. Do you know how to retrieve the response from the remote server using the callout method?


Message Edited by Losintikfos on 10-13-2008 07:56 AM
David VPDavid VP
Since it runs asynchronously there's not much use in returning something to the calling code (which will have moved on or finished in the meantime).

You would typically store the response of the call out in some fields in an object ...

Can you describe what you're trying to do ?


David

LosintikfosLosintikfos
David!

This is what i am trying to do!

1. Anytime a new Account is created a trigger will be fired to invoke an apex class;
2. This Apex class then takes  value from the AccountName and other fields to automatically invoke my remote service
3. This will process the request and return success confirmation.

Problem:
1. Finding it difficult to use trigger to invoke the Apex callout.







Message Edited by Losintikfos on 10-13-2008 08:21 AM
LosintikfosLosintikfos
Current code i am using:

Code:
global class ServiceAccount{
@future
static void createServ(){
Service__c sd;


Boolean rental = sd.Rental__c;
String alias = sd.Billing_Alias__c;
String freq = sd.Frequency__c;
String name = sd.Name;
Double ocost = sd.Operator_Cost__c;
Double scost = sd.Sales_Price__c;
Date start = sd.Contract_Start__c;
Date end_x = sd.Contract_End_Date__c;
Double qty = sd.Qty__c;

wsServiceAccount.ServiceAccountHttpSoap11Endpoint stub = new wsServiceAccount.ServiceAccountHttpSoap11Endpoint();
String call = stub.CreateService(rental, alias, freq, name, ocost, scost, start, end_x, qty);
return call;
}
}

 
Stack:
Method does not exist or incorrect signature: [wsServiceAccount.ServiceAccountHttpSoap11Endpoint].CreateService(Boolean, String, String, String, Double, Double, Date, Date, Double);





Message Edited by Losintikfos on 10-13-2008 08:33 AM
David VPDavid VP
Put your outbound call in an @future method and you'll be able to fire it from a trigger.
This will however not allow you to immediately display the result of your web service call to the user. (Don't know if you need this?)


Edit : I just saw the last message you added :

Method does not exist or incorrect signature: [wsServiceAccount.ServiceAccountHttpSoap11Endpoint].CreateService(Boolean, String, String, String, Double, Double, Date, Date, Double);

This method doesn't seem to exist in your class. Probably the number of arguments or their type is not correct.

David



Message Edited by David VP on 10-13-2008 05:54 PM
LosintikfosLosintikfos
Do you know why i can't pass the value from the fields from Service__c to invoke the method ServiceCreate?

I am doing something like this;

Code:
Service__c sb;

String name = sb.Name;

MainClass.endpoint stub = MainClass.endpoint();
    stub.ServiceCreate(name);

 This doesn't seems to work! do you have any clue what i am doing wrong?




David VPDavid VP
You declared but never initialized Service__c ?


Service__c sb = new Service__c(); //this will instanciate your object but all fields are still null
...

or you could pass your Service__c as a method argument ...


David
LosintikfosLosintikfos
I am doing somethis like this;

Code:
global class ServiceAccount{
   @future (callout = true)
     static void createServ(){
  Service__c sd = new Service__c();

            wsServiceAccount.ServiceAccountHttpSoap11Endpoint stub = new wsServiceAccount.ServiceAccountHttpSoap11Endpoint();
                   String call = stub.CreateService(sd.Rental__c, sd.Billing_Alias__c, sd.Frequency__c, sd.Name, sd.Operator_Cost__c, sd.Sales_Price__c, sd.Contract_Start__c, sd.Contract_End_Date__c, sd.Qty__c);  
                   return call;
        }
   }

and  still get the exception:
Save error: Method does not exist or incorrect signature: [wsServiceAccount.ServiceAccountHttpSoap11Endpoint].CreateService(Boolean, String, String, String, Decimal, Decimal, Date, Date, Double)   

David VPDavid VP
Can you copy the CreateService method from your wsServiceAccount in this thread ?

-David
LosintikfosLosintikfos
below is CreateService method David!

Code:
        public String CreateService(Boolean rental,String alias,String freq,String name,Double ocost,Double scost,DateTime start,DateTime end_x,Double qty) {
            wsServiceAccount.CreateService_element request_x = new wsServiceAccount.CreateService_element();
            wsServiceAccount.CreateServiceResponse_element response_x;
            request_x.rental = rental;
            request_x.alias = alias;
            request_x.freq = freq;
            request_x.name = name;
            request_x.ocost = ocost;
            request_x.scost = scost;
            request_x.start = start;
            request_x.end_x = end_x;
            request_x.qty = qty;
            Map<String, wsServiceAccount.CreateServiceResponse_element> response_map_x = new Map<String, wsServiceAccount.CreateServiceResponse_element>();
            response_map_x.put('response_x', response_x);
            WebServiceCallout.invoke(
              this,
              request_x,
              response_map_x,
              new String[]{endpoint_x,
              'urn:CreateService',
              'http://ws.essensys.billing.com',
              'CreateService',
              'http://ws.essensys.billing.com',
              'CreateServiceResponse',
              'wsServiceAccount.CreateServiceResponse_element'}
            );
            response_x = response_map_x.get('response_x');
            return response_x.return_x;

 

LosintikfosLosintikfos
Hi David,


I have found the error! Apex2WSDL was saving the value of date as DateTime; Changing this did clear the error.

Quick one! do you know how to store the response from the remote server?
LosintikfosLosintikfos
Do you know how to trigger @future method using before insert?

I am doing something like this;

Code:
global class ServiceAccount{
   @future 
     static void createServ(){
  Service__c sd = new Service__c();
  
     Boolean rental = sd.Rental__c;
     String alias = sd.Billing_Alias__c;
     String freq  = sd.Frequency__c;
  
            wsServiceAccount.ServiceAccountHttpSoap11Endpoint stub = new wsServiceAccount.ServiceAccountHttpSoap11Endpoint();
                   String call = stub.CreateService(rental, alias, freq);  
                   //return call;
        }
   }

Using the trigger:

Code:
trigger ServiceAccount on Service__c (before insert, before update) {
 ServiceAccount.createServ(trigger.new);
}

This then generates the error:
Method does not exist or incorrect signature: ServiceAccount.createServ(LIST:SOBJECT:Service__c)


Do you know how to go about this?

B
 


David VPDavid VP
Your method has the wrong signature (Trigger.new is a List of Service__c objects).

so in the ServiceAccount class you need :
static void createServ(List<Service__c> services) { ... }

-David


LosintikfosLosintikfos
Well If you read the language reference, it says List, Array of SObject cannot be a parameter to an @future method. Having said that didn't doubt your suggestion, did tried it and got the error:

Save error: Unsupported parameter type LIST:SOBJECT:Service__c    e



Message Edited by Losintikfos on 10-14-2008 02:09 AM
David VPDavid VP
I hadn't read that

(now I have) :smileysurprised:

The reference however says :
The parameters specified must be primitive dataypes, arrays of primitive datatypes, or collections of primitive datatypes

So perhaps you could build a list of the ID's and work with that ? (watch out for the governor limits though)

-David

gvgv

Hi David

 

I have the same issue as the previous poster. My trigger passes on a list of Ids like this

 

 

 

Opportunity_Sales_Goal__c[] lstOpportunitySalesGoal = [Select Id from Opportunity_Sales_Goal__c where Sales_Goal__c in :Trigger.newMap.keyset()];

 


 

 

My class which has the @future callout receives the parameter thus

 

 

@future (callout=true) public static void OpportunitySalesGoal(Opportunity_Sales_Goal__c[] opportunitySalesGoalArr) { DateTime currentTime = System.Now(); for(Opportunity_Sales_Goal__c opportunitySalesGoal:opportunitySalesGoalArr) { opportunitySalesGoal.Last_Sync_To_Parent__c = currentTime; } update opportunitySalesGoalArr; } }

 

 

 

I am getting an error in this  

 

Opportunity_Sales_Goal__c[] . 

 

The error message says

 

 

Save error: Unsupported parameter type LIST:SOBJECT:Opportunity_Sales_Goal__c

 

How do I got past this error

 

Thanks in advance 



jkucerajkucera

GV - you can't pass Sobjects as parameters into asynch methods.  From the annotations help:

 

"Methods with the future

annotation cannot take sObjects or objects as arguments. "

 

You can pass a list or set of ID's and then query for the objects inside the method. 

This was selected as the best answer