My question is, should clicking a button reload a page and perform an asynchronous callout?

It looks like its reloading the page after finishing the callout.

Custom Button : Execute JavaScript

{!REQUIRESCRIPT("/soap/ajax/15.0/connection.js")} 
{!REQUIRESCRIPT("/soap/ajax/15.0/apex.js")} 
location.reload();
sforce.apex.execute("MyQuote","callNetsuite",{lstQuoteID:"{!Quote.Id}"}); 

Apex class calls external application and updates the record field based on the response

global class MyQuote
{

    @future(callout=true)
    webservice static void callNetsuite(String lstQuoteID) 
    { 
       List<Quotes> requestQuote = new list<Quotes>();
       map<Id,Quote> mapquote = new map<Id,Quote>();
       list<Quote> lstQuote = [select Id,Name,Quote.Account.Name,Quote.Account.Netsuite_Customer_Id__c,
                                      (select Id,Quantity,UnitPrice,Product2Id,Product2.Name,Product2.Netsuite_Product_Id__c from QuoteLineItems) 
                                       from Quote where Id=:lstQuoteID];


       HttpRequest req = new HttpRequest();
       HttpResponse res = new HttpResponse();
       Http http = new Http();
       String responseBody;
       String jsonbody = '[{"trandate":"4/1/2015","terms":"","shipaddresslist":"","recordtype":"salesorder","otherrefnum":"test quote SO1","item":                       [{"quantity":3.00,"item":"128","internalid":"","amount":399.00},{"quantity":3.00,"item":"130","internalid":"","amount":89.99}],"internalid":"","externalid":"0Q028000000L39DCAS","entity":"1249","billaddresslist":""}]'

       String authorizationHeader = 'NLAuth nlauth_account=XXXXX,nlauth_email=XXXXX,nlauth_signature=XXXXX';
       String endpoint = 'https://rest.na1.netsuite.com/app/site/hosting/restlet.nl?script=598&deploy=1';

       req.setHeader('Authorization', authorizationHeader);
       req.setHeader('Content-Type','application/json');
       req.setMethod('POST');
       req.setTimeOut(120000) ; 
       req.setEndpoint(endpoint);
       req.setBody(jsonbody);


       if (!Test.isRunningTest())
       {
           try 
           {
               //Send endpoint to Netsuite
               res = http.send(req);
               responseBody = res.getBody();
               System.debug('responseBody:'+responseBody);
               System.debug('BodyResponse:'+res.toString());
           } catch(System.CalloutException e) {
             System.debug(res.toString());
           }
      }else {
        // dummy data
        responseBody = '200';
       }


       if(responseBody != null && responseBody != '')
       {
            List<resQuotes> quotelst = (List<resQuotes>)JSON.deserialize(responseBody,List<resQuotes>.class);
            list<Quote> updateQuotelst = new list<Quote>();
            system.debug('quotelst:'+quotelst);
            for(resQuotes resp : quotelst)
              {

                 updating the quote record based on response 

              }



       }

   }    

   global class resQuotes
   {
     webService String recordtype;
     webService String internalid;
     webService String externalid;
     webService List<resItem> item;
     webService String salesordernumber;
     webService String issuccess;
     webService String errorcode;
     webService String errormessage;
   }

   global class resItem 
   {
     webService String internalid;
     webService String externalid;
     webService String status;
    }

}

You should look into Queueable Apex and Queueable Interface instead of using a future call, this would mean the page would instantly reload and the APEX would fire off asynchronously.

Can you try this?

{!REQUIRESCRIPT("/soap/ajax/15.0/connection.js")}
    {!REQUIRESCRIPT("/soap/ajax/15.0/apex.js")}

    setTimeout(function(){
        sforce.apex.execute("MyQuote","callNetsuite",{lstQuoteID:"{!Quote.Id}"});
    },333);
    setTimeout(function(){
        location.reload();
    },334);

There is no need to use future method in your webservice class. I have tried with similar code in my org and callout is performed successfully after reloading the window. However, What you know can do is to catch the response and show a popup based on response so that user will know the status of callout and then reload the window, if necessary. The callout should take not a lot of time or else there will be read time-out error.

The callout will be asynchronous if you use future annotation like below.

Also, sforce.connection has onSuccess and onFailure parameter and runs in asynchronous mode.

Button:

var queryResult = sforce.connection.execute("ClassName","MethodName", MethodParam:"recid",{ 
onSuccess : success, 
onFailure : failure 
}); 

function success(result){ 
var ParentDocId = result.getArray("records");
location.reload();
} 

function failure(error) { 
alert("An error has occurred " + error); 
}

Class:

webservice static void method1(){
method2();
}

@future(callout=true)
public static void method2(){}
  • Your answer its correct. but you can do the same without change the class – Torsen Mar 14 '17 at 8:13

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.