0

I have the following code below. The field generatedToken gets populated in getTokenFromA(), but when I access it in PutA() it is null. I have tried defining it as just static (without public) and received the same results. Any help in defining this correctly would be appreciated.

public class OurCallout {
    public static String generatedToken {set; get;}
    static String errorMessage {set; get;}
    static String TimelineResponse {set; get;}
    
    @future(callout = true)
    
    public static void getTokenFromA() {    
        HttpRequest req = new HttpRequest();
        req.setMethod('POST');
        req.setHeader('Authorization', 'Basic ' + EncodingUtil.base64Encode(Blob.valueOf('hard_coded_client_id' + ':' + 'hard_coded_client_key')));
        req.setHeader('content-type', 'application/x-www-form-urlencoded');
        req.setEndpoint('https://ourdomain.com/token');
        req.setBody('grant_type=client_credentials');

        Http http = new Http();
    
        try{
            HTTPResponse res = http.send(req);
            JSONParser objParse = JSON.createParser(res.getBody());
            while (objParse.nextToken() != null) 
            {
                if (objParse.getCurrentToken() == JSONToken.FIELD_NAME && objParse.getText() == 'access_token')
                {                               
                     objParse.nextToken();
                    generatedToken = objParse.getText();
                }
            }
        } 
        catch(Exception ex){
            errorMessage = ex.getMessage();
            System.debug('Exception :' + ex.getMessage());
        }
    }

        public static void PutA() {
            getTokenFromA(); // Generate new access token before calling bellow API
            if(generatedToken == null ) {
                TimelineResponse = 'Error while generating token, so unable to get messages. Check your debug log.';
                return;
            }
            try{
                HttpRequest objReq = new HttpRequest();
               objReq.setEndpoint('https://ourdomain.com/ourendpoint');
                objReq.setMethod('POST');
                objReq.setHeader('Authorization', 'Bearer ' + 'hard_coded_token');
                objReq.setBody('{"record_id": 5640,"Email": "[email protected]"}');
                Http objHttp = new Http();
                HTTPResponse objRes = objHttp.send(objReq);
                TimelineResponse = objRes.getBody();
                if(String.isBlank(TimelineResponse)){
                    TimelineResponse = objRes.toString();
                }
             }
             catch(Exception ex)
             {  errorMessage = ex.getMessage();
                System.debug('ExceptionP :' + ex.getMessage());
             }
    }
}
2
  • 1
    Your try/catch blocks are only making it harder for you to detect any errors that are happening. You should remove them and let the exceptions be uncaught.
    – Derek F
    Commented Oct 27, 2021 at 20:47
  • @DerekF I will take them out...but I do not think that is what the issue is here. genereatedToken gets a value in getTokenFromA(). I had a debug statement there and verified it contained data.
    – SFApexUser
    Commented Oct 27, 2021 at 21:12

2 Answers 2

1

Because getTokenFromA is marked with @future it will not run in the current transaction that calls PutA but will run sometime later. So generatedToken will always be null.

You will need to restructure your logic e.g. make the second HTTP call from inside the getTokenFromA method.

1
  • Thank you. I will make this one method instead of two. The examples I found online had the two methods - but as you indicated I do not actually need them.
    – SFApexUser
    Commented Oct 28, 2021 at 11:02
3

Future methods are called asynchronously. This means that getTokenFromA() will not start until putA() has finished, and in fact, won't even be in the same logical transaction as the original method call. I don't see a reason to use @future for getTokenFromA() (without more context, this is an X-Y Problem), but given what is in the question, you should remove @future(callout=true) from your code.

1
  • Thank you. I am doing a call out from a trigger to this class - everything I read and found indicated I need the @future statement.
    – SFApexUser
    Commented Oct 28, 2021 at 11:01

You must log in to answer this question.

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