0

I'm new to working with API's and code in general, I have been challenged to create an API to collect data to input into Salesforce records, this will be invoked by a trigger.

Currently, I'm running the tests on the Open Weather Map API.

I'm preforming the callout as a 'GET' Method and returning the response which I deserialize into variables that I would like to put into the Account record.

Code Example

trigger RedTrigger on Account (before Update) {
    Public String ShowThisResult = null;
    @future(callout=true)
   public static void GetAPIAsyn ()
    {

        Http http=new Http();
        HttpRequest request=new HttpRequest();
        request.setEndPoint('https://api.openweathermap.org/data/2.5/weather?q=Ulverston&APPID=6a4199d8698bb67cc604e3fb8082599d');
        request.setMethod('GET');
        HttpResponse response=http.send(request);

        if (response.getStatusCode() == 200) {
            ShowThisResult = response.getBody();
            Map<String,Object> results=(Map<String,Object>)JSON.deserializeUntyped(response.getBody());
            String.valueOf(results.get('weather'));
            System.debug(ShowThisResult);
            System.debug(response);
            System.debug(response.getStatusCode());
        }

        else {
            System.debug('The status code returned was not expected: ' +
                response.getStatusCode() + ' ' + response.getStatus());

            }

}
    for (Account a : Trigger.new) {
        a.value1__c = ShowThisResult;
        }
}

I have tried doing it as separate classes using @future(callout=true) but I can't get it working for me.

Here are the fields on Account that I'm trying to populate with the collected values-

Populate Thes Fields On Account

It seems 'ShowThisResult' isn't populating because when I run this on account it pulls through as a blank value. Any pointers/guidance will be greatly appreciated thank you.

Updated Code:- Trigger

trigger GreenTrigger on Account (before update) {
for (Account objAccount : Trigger.new) {
        //make webservice callout 
        GreenTriggerHandler.GreenAPI(objAccount.Value1__c, objAccount.Value2__c);

    }
}

Updated Apex Code:-

public class GreenTriggerHandler {
 @future (callout=true)
    public static void GreenAPI(string Value1, string Value2) {
        try{
            Http http=new Http();
            HttpRequest request= new HttpRequest();
            request.setEndPoint('https://api.openweathermap.org/data/2.5/weather?q=Ulverston&APPID=6a4199d8698bb67cc604e3fb8082599d');
            request.setMethod('GET');
            HttpResponse response=http.send(request);

            response = http.send(request);
            if (response.getStatusCode() == 200) {
                Map<String,Object> results=(Map<String,Object>)JSON.deserializeUntyped(response.getBody());
                Value1 = String.valueOf(results.get('weather'));
                System.debug('Response-' + response);

            }
            Account Acc = new Account();
                Acc.value1__c = Value1;
        }
        catch(System.CalloutException e){
            System.debug('Error-' + e.getMessage());   
        }
    }
}

Tried a different method but think im still way off. Would it be okay to show me code snippet cheers?

Thanks for the help.

  • 3
    I can't say this is the issue or not, but you shouldn't be creating a separate class within the trigger code itself. Either put the full logic in the trigger directly (not advisable) or put the logic in a helper class (this is the ideal architecture). That helper class can then house the future method. The reason I say this is that you have a member variable that is being accessed by the future method, but the trigger itself isn't a class, so I don't think the future method is able to see it correctly. So I would start with separating it to a separate class first and going from there. – Roti Oct 25 '19 at 16:25
4

You have a trigger looking like you are making an asynchronous (@future) to method getAPIAsyn but in fact, this method is never called.

Furthermore, even if the trigger did call this method, it executes asynchronously and the bottom of the trigger that loops through Trigger.new will execute BEFORE the @future method even starts - hence why no value in the account field.

The pattern to use is to (because triggers can't do synchronous callouts)

  • Invoke the future method with a list of accountIds taken from Trigger.newMap.keySet()
  • execute all the callouts (there are some issues here to think about with governor limits on # of callouts per transaction)
  • Do the account updating in the @future method once the callout has returned

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.