StartAllOfTheThings(); - How to Solve a Deployment Headache
Update 29th June, 2012
This post has now been made somewhat redundant thanks to some great work by Zach McElrath, who has built an application to try and negate our developer woes with regards to scheduled jobs.
One of my biggest bugbears when deploying Apex code to another org, is when you have a schedulable
(yes, that is a word in the world of force.com development!) Apex class scheduled and it uses methods in a class that you're trying to update — many developers will have come across this, it stops you from deploying until you've cancelled the scheduled job. This isn't the tedious part though, that part is starting the jobs up again, you need to schedule each one, remembering the correct settings and making sure you don't forget any (or indeed, schedule any twice which is something I've done before now).
I understand why you shouldn't be able to replace code used by a scheduled job, and why even if you don't change the code it uses that if a class needs to be recompiled it's going to have a cascading effect, most likely requiring recompilation of the scheduled class (though I don't know about the specifics of the platform in that area, it would appear to involve something like static linking). This doesn't mean it's not irksome though, especially on orgs where you have many scheduled jobs running and you just need to deploy a minor change.
Any easy way to resolve this is to use code to schedule your jobs, so although you still have to stop them, starting them again is a one-liner in the System Log window, where you run a static method which sets everything up:
MyJobStarter.StartAllOfTheThings();
The class is very simple:
public with sharing class MyJobStarter
{
public static void StartAllOfTheThings()
{
try
{
System.schedule('MyJob1', '0 59 0-23 * * ?',
new SomeSchedulableClass());
System.schedule('MyJob2', '0 0 8 ? * 1,2,3,4,5,6,7',
new SomeSchedulableClass());
}
catch (Exception e)
{
// Do something here if needed
}
}
}
As you can see, System.Schedule()
uses a cron-like syntax to specify the schedule for the job you're starting and you can find everything you need in the documentation, but for the two jobs in the example "MyJob1" runs on the 59th minute of every hour, and "MyJob2" runs at 8am every day. I'm aware of others who have taken this further, and created Visualforce pages to fulfill their needs with regards to starting and stopping jobs, but so far for me this has proved to be a nice, simple solution. I still have to stop the jobs, but that was never the tedious part and now I can start them up with a single line of code in the System Log.
Update
As highlighted by @andymahood__c, something I neglected to mention here is another benefit of the System.Schedule method: it can be used to schedule jobs to run more frequently than the UI options allow, up to a maximum frequency (I believe) of every 15 minutes.