I have a Schedulable
class that calls out to a third party GPS service. The problem I'm running into is that when I try to do the initial schedule (via anonymous execution) I get the error:
Not Serializable: System.Http
Is there something I can do to get around it? I need to schedule this code to run every 90 seconds so I can have a near real time display of all of our vehicles' GPS positions. For what it's worth, here's the code:
global class vNextGpsScheduledUpdate implements Schedulable {
private vNextGps gps = new vNextGps('username', 'password');
global void execute(
SchedulableContext sc1) {
if (sc1 == null) {
return;
}
/// Get a list of vehicles in the GPS service
List<vNextGpsVehiclesLocation> l2 = gps.getVehiclesLocations();
/// Get a list of vehicles in the database
List<vNextVehicle__c> l1 = getVehiclesFromDb();
/// Loop through each vehicle in the database
for (vNextVehicle__c v1 : l1) {
/// Loop through each vehicle in the GPS service
for (vNextGpsVehiclesLocation v2 : l2) {
if (v1.Name == v2.name) {
v1.GPS_Coordinates__Latitude__s = v2.latitude;
v1.GPS_Coordinates__Longitude__s = v2.longitude;
v1.GPS_Timestamp__c = v2.timestamp;
v1.Odometer__c = v2.odometer;
/// Break out of the inner loop if the name matches
break;
}
}
}
/// Update all vehicles in the database
update l1;
/// Schedule the next run of this job
DateTime a1 = DateTime.now().addSeconds(90); /// nextRun
String b1 = String.valueOf(a1.minute()), /// minute
b2 = String.valueOf(a1.second()), /// second
b3 = b1 + ' ' + b2 + ' * * * ? * vNextGpsScheduledUpdate', /// cronValue
b4 = 'vNextGpsScheduledUpdate ' + a1.format('hh:mm'); /// jobName
vNextGpsScheduledUpdate c1 = new vNextGpsScheduledUpdate();
System.schedule(b4, b3, c1);
System.abortJob(sc1.getTriggerId());
}
@testVisible
private List<vNextVehicle__c> getVehiclesFromDb() {
return [
SELECT Name,
GPS_Coordinates__Latitude__s,
GPS_Coordinates__Longitude__s,
GPS_Timestamp__c,
Odometer__c
FROM vNextVehicle__c
WHERE (Is_Active__c = true)
AND (GPS_Active__c = true)
];
}
}
UPDATE
I managed to get it working using @sfdcfox's answer. In my original version, I had an inner class in my vNextGps
class that I used to mimic C#'s WebClient
class since I was porting the code from pre-existing C# code. Because of that the scheduler couldn't serialize the class. I have since removed the inner class and merged the functionality directly into the method that needed it.
Sadly, that was still not enough because the scheduler then complained about calling out. To resolve that issue I moved the call out code into a separate Queueable
class. In turn the Scheduleable
class now just adds it to the queue, and schedules itself again. So far, the Queueable
class is being processed almost immediately thereafter, so the end result is what I needed. Oh, I did have to annotate the Queueable
methods with @future (Callout = true)
for everything to finally work.
Way too much hoop jumping to get it to work, but at least it works now.
vNextGpsScheduledUpdate
, the private variablegps
is instantiated and presumably does the HTTP authentication to the remote service. But the scheduled class hasn't yet executed as that won't happen until the CRON scheduled time occurs. This seems out of sequence to me – cropredy May 9 '15 at 0:14gps
variable is instanced it does not make any requests at that time. API on the other side is stupid and the authentication is pointless (always gives the same token, so I just hard coded it in). The only time a call out is done is whengps.getVehiclesLocations()
is called, which is during theexecute
method's lifetime. – Gup3rSuR4c May 9 '15 at 0:30execute()
starts? There will be two log files if you get to theexecute()
– cropredy May 9 '15 at 0:36