3

I am pretty stumped - I have a trigger on a custom object that calls a helper class that calls a future callout method. When I call the trigger, the helper class is called but I can't seem to get into the future method with the callout in it. It does work when I try getting into a future method with no callout. Is there a rule with trigger/future/callouts that I am unaware of?

I have also tried calling the future method with the callout from a process builder & @InvocableMethod with no success.

It seems to really hate the HTTP callout. Any ideas why it is getting caught up on this?

Also - the debug logs are not showing any future calls and nothing is showing in Apex Jobs so I know it is not running at all.

calcLink() is called from the trigger.

I know the http is working because I am able to invoke it manually with a button that calls to calcLinkGeneratorOnDemand()

I also know having a query in the loop is bad practice but it is not the cause of any blockers, I can see that a.Name has a value.

global with sharing class CalculatorClass {

public void calcLink(Map<Id, FPC_Funding_del__c> newfundIds, Map<Id, FPC_Funding_del__c> oldFundIds){
    for(FPC_Funding_del__c currentFunding : newfundIds.values()){
        Account a = [Select Id, Name from Account where Id = :currentFunding.Lender_ID__c LIMIT 1];
        if(a.Name.contains('Company Name')){
            callTokenizer(currentFunding.Id);
        }
    }
}

@InvocableMethod 
global static void pbToTokenizer(List<Id> fundingIdList) {
    system.debug('pbToTokenizer ' + fundingIdList);
    if(!System.isFuture()) {
        for(Id fID: fundingIdList){
            system.debug('what is this value: ' + fID);
            callTokenizer(fID);
        }    
    }
}

@future(callout=true)
global static void callTokenizer(Id funderId){
    Map<String, String> tokenCredMap = new Map<String, String>();
    Id parsedId;
    String parsedToken;
    try{
        //------->Authorization<--------------
        HttpRequest req = new HttpRequest();
        List<LinkShorteningAPI__C> mcs = LinkShorteningAPI__c.getall().values();
        String endpoint = mcs[0].Endpoint__c ;//STS
        String apikey = mcs[0].Authorization__c;
        String token = mcs[0].Service_Endpoint__c ;
        req.setMethod('POST');
        req.setEndpoint(Endpoint);
        req.setHeader('Content-Type', 'application/json');
        req.setBody('"' + apikey + '"');
        Http h = new Http();
        HttpResponse res = h.send(req);
        String authcred = res.getBody();
        String svcAuth = 'token ';
        svcAuth += authcred;
        if(svcAuth == 'token {"Message":"An error has occurred."}'){
            throw new GenericException('STS Service is down. Please contact your system admin.');
        }

        //------->POST<-----------------
        HttpRequest req1 = new HttpRequest();
        req1.setMethod('POST');
        req1.setEndpoint(token);
        req1.setHeader('Authorization', svcAuth);
        req1.setHeader('Content-Type', 'application/json');
        req1.setBody('[{"ID":"' + funderId + '","Properties":{"fundingId":"' + funderId + '"}}]');

        Http h1 = new Http();
        HttpResponse res1 = h1.send(req1);
        String tokencred = res1.getBody();

        JSONParser parser = JSON.createParser(tokencred);

        //parse and map the returned string
        while (parser.nextToken() != null) {
            if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) && (parser.getText() == 'Id')) {
                parser.nextToken();
                parsedId = parser.getText();
            }
            if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) && (parser.getText() == 'Token')) {
                parser.nextToken();
                parsedToken = parser.getText();
            }
            tokenCredMap.put(parsedId,parsedToken);
        }

        String tokenCredentialString = tokenCredMap.get(funderId);
        if(tokenCredentialString != null && tokenCredentialString != ''){
            fpc_funding_del__c f = new fpc_funding_del__c(Id= funderId,CalculatorLink__c= tokenCredentialString);
            update f;
        }
    }
    catch(Exception e){
        system.debug('there has been an error: ' + e);
        throw e;
    }
}

public PageReference calcLinkGeneratorOnDemand(){
    String funderId = ApexPages.currentPage().getParameters().get('funderId');
    callTokenizer(funderId);
    return new pageReference('/' + funderId);
}

}
2
  • 3
    the future transaction will appear as a separate entry in the debug log; unless a.Name does not contain Company Name, the future should start
    – cropredy
    Commented Dec 10, 2021 at 22:56
  • Make sure that the value in mcs[0].Endpoint__c is registered under Setup/Remote Site Settings. Also, there is a limit on the number of @future calls per transaction. It is better to call callTokenizer() outside the loop and pass a set of Ids instead of a single Id.
    – Fernando F
    Commented Dec 11, 2021 at 8:35

1 Answer 1

1

As cropredy already mentioned, future logs will be in a different thread called FutureHandler. If you don't see a FutureHandler entry in your logs, then if(a.Name.contains('Company Name')) is evaluating to false.

5
  • I am system.debugging and can see that a.Name has a value and I can see that I am able to get into that conditional block...maybe I am not putting on the right debug logs? I have it logging my activity, Platform Integration activity and Automated Process activity
    – Olivia
    Commented Dec 11, 2021 at 19:04
  • Just be to clear, you are in fact, checking the Logs tab in the lower pane of the Developer Console and looking for the Future Handler entry there, right? Commented Dec 14, 2021 at 22:59
  • I am putting debug logs on and checking the debug logs page in salesforce (not the dev console) because it gives more data. I can see FutureHandler logs for other callouts, just not mine. The more I think about it, there has to be a rollback happening at some point...or it's an order of execution issue?
    – Olivia
    Commented Dec 15, 2021 at 17:15
  • Is your calling class (in this case your trigger class) wrapping the method call new CalculatorClass().calcLink() in a try catch block? I ask this because your future method does not handle any possible exceptions. All it does is throw them thereby expecting the calling class to handle it instead. It's possible that an exception is happening and is not being properly handled. Thus, maybe some implicit rollback is happening Commented Dec 15, 2021 at 21:36
  • I found that the callouts were not running against my user but instead on an automation user the company created. This is why I couldn't see any logs. I am tracking that user now and able to see that the future is being called but only when I set the trigger up as an after update. This means to me that something is happening with the after insert that is rolling it back...
    – Olivia
    Commented Dec 16, 2021 at 14:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .