1

I need to make some changes to a schedulable class that inserts Case Share objects for our custom permissioning model. When trying to make changes to the class, the error is thrown that the class has pending jobs in progress. I am able to find the jobs under Scheduled Jobs, but they were written and scheduled years ago by consultants.

Is there a way to recreate these jobs identically after I have deleted them (in order to make changes to the class)? Since they are not editable, I cannot look in and see the components like what classes/methods are called and when it is scheduled to run.

4
  • You can't click on Manage next to the Job?
    – Adrian Larson
    Commented Mar 14, 2016 at 16:10
  • No, there is only the option to delete it.
    – Chris P
    Commented Mar 14, 2016 at 16:12
  • What if you log in as the user who submitted it?
    – Adrian Larson
    Commented Mar 14, 2016 at 16:12
  • Same situation. Logged in as the user that submitted it and there is only the option to Delete rather than manage.
    – Chris P
    Commented Mar 14, 2016 at 16:14

3 Answers 3

2

If the event was scheduled via the UI, you should be able to get the information you want via SOQL. Here's the problem: CronTrigger has most of the data points you need, which you can access through CronJobDetail if you query on Name, which you can see. But the only way to determine which ApexClass is scheduled is via AsyncApexJob, which has no relationship to either SObject.

An unofficial source claims that the CreatedDate should match if the job was scheduled through the UI. So if that is the case, you should be able to get the data with two queries. The following worked for me in Execute Anonymous to infer the necessary data:

CronTrigger jobData = [
    SELECT CreatedDate, CronExpression, EndTime
    FROM CronTrigger WHERE CronJobDetail.Name = 'Job I Want To Delete'
];
AsyncApexJob execution = [
    SELECT ApexClass.Name FROM AsyncApexJob
    WHERE CreatedDate = :jobData.CreatedDate
];
system.debug(jobData.EndTime);
system.debug(jobData.CronExpression);
system.debug(execution.ApexClass.Name);

From there, you can use System.schedule, though it may get you or someone else into a deeper conundrum down the road.

Schedulable instance = (Schedulable)Type.forName(execution.ApexClass.Name).newInstance();
system.schedule('Job No Longer Deleted', jobData.CronExpression, instance);

However, it may be preferable to simply interpret the CronExpression for yourself and still schedule through the UI. For example, if you scheduled it to execute at 1:00 PM each weekday, it would look like: 0 0 13 ? * 2,3,4,5,6. If it's scheduled through the UI in the first place, then you will get the hour from the third component, and the days of the week from the final component. 1 indicates Sunday, 2 indicates Monday, etc.

2
  • This is a very helpful idea. The first query, when I run it in execute anonymous, I get a Query Exception in row 5 for no rows for assignment. I would think that would only happen if there was no class associated with the job, but that doesn't make much sense.
    – Chris P
    Commented Mar 16, 2016 at 14:58
  • Or if they were scheduled via Execute Anonymous. Maybe try expanding it to a range of the next five seconds. Hopefully only one record will match...
    – Adrian Larson
    Commented Mar 16, 2016 at 15:11
1

If the Schedulable class is running at the same time on the same day(days), then it is highly likely that it was scheduled from Develop | Apex Classes | Schedule Apex Class. In this case, once you delete the job, you can reschedule the same way. It is not important to have any more detail, just use the point and click scheduler.

If the Schedulable class is running multiple times per day but at the same times each day, then it is likely that it was scheduled via anonymous APEX. Once you delete the job, you can reschedule the same way - although if the schedulable class has a custom constructor, you'll need to see what is passed as arguments before rescheduling. See the doc on how to construct a CRON expression to match the schedule ascertained from looking at the pattern of past runs.

If the Schedulable class is running at distinct/unique times with no particular pattern, then it is likely that it is scheduled by some other system event (trigger, conclusion of some other job, VF controller action, REST call, ...). Here, once you delete the job, it will restart when that event recurs

0

This is a well known issue with schedulables. They can get "stuck" if you don't run them as instances of the schedulable class. If you can delete it, that would be your best way out of your situation. I suggest you update the class to add a custom setting to allow you turn the class on and off or else run it as a new instance of itself which checks a boolean flag that's set on a control class.

You can of course calculate when the jobs were supposed to run, and backtrack to recreate them if that's what you're asking. Without seeing your code, it's difficult to answer your question, but I'd expect that the schedulable reschedules itself to run again upon completion of each job. You'll need to figure out how many instances of it the original developers had running or if there's only one. If the latter, it should be simple enough to backtrack using the settings in the chron trigger.

You must log in to answer this question.

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