2

I am trying to make a TimeZone class that does the process to get a time zone. I am using the Google API's. In order to get the timezone you have to make a callout to the Google Geocode API and get the latitude and longitude coordinates. Then you have to use those coordinates to call the Google TimeZone API to receive the timezone. Right now I have a trigger that fires an ID to a class1. The class1 then calls my TimeZoneclass2. I have tried multiple ways to work around so that I can receive my timezone inside class1 after calling TimeZoneclass2. I keep getting null values returned and I think its because my class2 moves on to the next lines of code, while the TimeZoneclass2 is waiting for the response from the callouts, so therefore i get 'null' values. Any help would be appreciated. I've going on the third day of trying to get this to work for me. Thank you!

public class TimeZoneUtility
{   
    public static String Latitude       {get; set;}
    public static String Longitude      {get; set;}
    public static String TimeZone       {get; set;}

    public static void returnTimeZone(String address, String city, String state)
    {
        getGeoCode(address, city, state);       
        System.debug('Derrick: Lat: ' + Latitude);
        System.debug('Derrick: LNG: ' + Longitude);
        getTimeZone(Latitude, Longitude);
        System.debug('Derrick: TimeZone: ' + TimeZone);

    }

    @future(callout = true)
    public static void getGeoCode(String address, String city, String state)
    {
        address = address.replace(' ', '+');
        city    = city.replace(' ', '+');
        state   = state.replace(' ', '+');

        String endpoint = 'https://maps.googleapis.com/maps/api/geocode/xml?address=' +address+ ',+' +city+ ',+' +state+ '&key=AIzaSyBGiCxIWQVjorNHlbTCA1-U-3XALdJ_Qb8';

        // Instantiate a new http object
        Http h = new Http();

         // Instantiate a new HTTP request, specify the method (GET) as well as the endpoint
        HttpRequest req = new HttpRequest();
        req.setEndpoint(endpoint);
        req.setMethod('GET');


        // Send the request, and return a response
        HttpResponse res = h.send(req);  

        Dom.Document doc = new Dom.Document();
        doc.load(res.getBody());


        Dom.XMLNode xroot = doc.getRootElement();
        String status = xroot.getChildElement('status', null).getText();

        Dom.XMLNode xrCharge = xroot.getChildElement('result', null).getChildElement('geometry', null).getChildElement('location', null);

        Latitude  = xrCharge.getChildElement('lat', null).getText();
        Longitude = xrCharge.getChildElement('lng', null).getText();
        System.debug('Derrick: LAT: ' + Latitude);
        System.debug('Derrick: LNG: ' + Longitude); 

     }

    @future(callout = true)
    public static void getTimeZone(String lat, String lng)
    {
        System.debug('Derrick: LAT: ' + lat);
        System.debug('Derrick: LNG: ' + lng);

        String endpoint = 'https://maps.googleapis.com/maps/api/timezone/xml?location=' +lat+ ',' +lng+ '&timestamp=1331161200&key=AIzaSyDu60hEW-wF2d2FhOS-xCszEAtSSWjbZYk';

        // Instantiate a new http object
        Http h = new Http();

         // Instantiate a new HTTP request, specify the method (GET) as well as the endpoint
        HttpRequest req = new HttpRequest();
        req.setEndpoint(endpoint);
        req.setMethod('GET');
        //req.setMethod('POST');  // sets the type of method to be used for the HTTP request
        //req.setBody(body);   

        // Send the request, and return a response
        HttpResponse res = h.send(req); 

        //System.debug(res.getBody());

        Dom.Document doc = new Dom.Document();
        doc.load(res.getBody());

        Dom.XMLNode xroot = doc.getRootElement();
        TimeZone = xroot.getChildElement('time_zone_name', null).getText();
        System.debug('Derrick: TimeZone: ' + TimeZone);

    }

1 Answer 1

3

Your methods getGeoCode and getTimeZone are both decorated with the @future(callout = true) annotation.

That makes them asynchronous. With Salesforce this means that those methods will execute at some time after the calling context/transaction has completed. There is no way to return results to the calling context.

Are you in a trigger context when calling these methods? That does necessitate the future calls as you can't make callouts in a trigger. You would need to modify the future methods to do whatever post callout processing is required.

If you aren't in a trigger context you could make variations of those methods that don't have the future annotation.

I'll often do something like:

@future(callout = true)
public static void getGeoCodeFuture(String address, String city, String state)
{
    getGeoCode(address, city, state);
}

public static void getGeoCode(String address, String city, String state)
{
    // implementation
}

See Future Annotation.

3
  • all the trigger does is grab an ID then sends to a class that does all the work. the class then calls the timezone class that has the callouts. so yeah i'm in a trigger context.
    – twiggler
    Apr 23, 2015 at 14:49
  • Daniel, that is the format I used but I still couldn't get the value to be returned to the class calling it. And after reading thread after thread it's not gonna work. So lucky for me I really didn't need the value returned instantly like I originally thought. What I did was make an extra method in my TimeZone class that will update the record I needed after the callout response was complete. It took 3 days but i finally got it to work for what I needed. Definitely a learning experience. Thanks for your reply
    – twiggler
    Apr 23, 2015 at 19:36
  • 1
    @twiggler Glad you got it sorted. Sounds like you ended up with the same approach this I suggested in the third paragraph. Apr 23, 2015 at 21:23

You must log in to answer this question.

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