9

I am trying to execute a web service call to our backend system when the opportunity is closed/won. I am attempting to do a POST to our endpoint. All the api call is really carrying the account name and a few structural detail back (All listed below). My problem is that when the trigger executes I get the following error in the debug logs "System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out".

The Process Builder Passing in the company name: enter image description here

APEX Class

public class Play2 {
@TestVisible static HttpResponse res;

@InvocableMethod
public static void sendNotification(List<String> name) {



    HttpRequest req = new HttpRequest();
    Http http = new Http();
    String payload = JSON.serialize(
        new Map<String, String> {
            'companyName' => name.get(0),
            'salesforceAccountType' => 'Company',
            'salesforceSynchStatus' => 'Enabled'
        }
    );

    req.setEndpoint('https://TheEndPoint');
    req.setMethod('POST');
    req.setHeader('Authorization', 'The Mighty API KEY');
    req.setHeader('Content-Type', 'application/json');

    req.setBody( payload );
    req.setCompressed(true); 

    try {
        System.debug('Point 1');
        res = http.send(req);
        System.debug('Point 2');
    } catch(System.CalloutException e) {
        System.debug('Callout error: '+ e);
        System.debug(res.toString());
    }
}
}
10

Apex can be annoying like that: limitations in termos of callouts and DML. What we've done to work around that is to make callout in the future method. Your invocable would call the future and pass the map. The future would construct the request and send it out. Your future should be annotated with @future(callout=true) to be able to make callouts.

  • Thanks...I guess then I would have to use a traditional trigger and can no longer use the process builder to execute the call. Makes sense! – Vik Apr 29 '16 at 19:56
  • Have you tried? I think you can use futures from inside an invocable method – mkorman Apr 29 '16 at 20:00
  • I'm trying to do the same - execute an invocable method which makes an HTTP Request; getting the same error. When I mark @future(callout=true) I get an error: Future methods cannot be marked as InvocableMethod. Is there a way around that? – zainogj Aug 19 '16 at 20:36
  • Found this article which explains it well. Make the invocable method a wrapper which calls the future method which makes the call out. – zainogj Aug 19 '16 at 20:52
  • I have the same issue as @zainogj I have an apex method that creates a user and then adds sharing to a case and updates some other fields. I need to also do a callout at this point which I was doing through invocable methods. However because I'm doing a setup and non setup task the case sharing and case updates need to happen in a future method, this calls the process which is now in future context and thus can't call another future method... – thegogz May 25 '17 at 11:07
0

Try this

public class Play2 {
@TestVisible static HttpResponse res;

@InvocableMethod

public static void sendNotification(List<String> name) {


calloutmethod(name);

}

@future(callout=true)

public static void calloutmethod(List<String> name){
  // Your callout logic
}

}
  • 2
    without an explanation, this answer does not prove very useful. Please update accordingly and take some time to read How to Answer. Thanks – glls Oct 17 '17 at 2:13
0

@InvocableMethod makes the method visible to process builder.

@future(callout=true) makes the process builder able to use methods that callout since there can only be asyncronous callouts allowed from an invocable method.

public static void calloutmethod(List name){} - the @future callout needs to be in a separate method that is called by the @invocableMethod sendNotification(List name) since you cannot callout directly from a method annotated with the @invocableMethod.

-- @TestVisible static HttpResponse res; is probably his unique way of replying with a mock callback and uses this in his test classes. You should at least implement HttpCalloutMock in your tests against this the Play2 class.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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