Apex スケジューラを使用したジョブのスケジュール

学習の目的

この単元を完了すると、次のことを理解できるようになります。
  • スケジュール済み Apex を使用するケース。
  • スケジュール済みジョブを監視する方法。
  • スケジュール済み Apex の構文。
  • scheduled メソッドのベストプラクティス。

スケジュール済みの Apex

Apex スケジューラを使用すると、Apex クラスの実行を遅らせて、指定した日時に実行できます。このスケジューラは、Apex 一括処理を使用した日次または週次のメンテナンス作業に最適です。スケジューラを活用するには、Schedulable インターフェースを実装する Apex クラスを記述して、特定のスケジュールで実行されるようにクラスをスケジュールします。

スケジュール済み Apex の構文

特定の時間に実行される Apex クラスを呼び出すには、まずクラスに Schedulable インターフェースを実装します。次に、System.schedule メソッドを使用して、特定の時間に実行されるようにクラスのインスタンスをスケジュールします。

global class SomeClass implements Schedulable {
    global void execute(SchedulableContext ctx) {
        // awesome code here
    }
}

このクラスは Schedulable インターフェースを実装し、このインターフェースに含まれるメソッド (execute メソッド) のみを実装する必要があります。

このメソッドのパラメータは SchedulableContext オブジェクトです。クラスがスケジュールされると、スケジュール済みジョブを表す CronTrigger オブジェクトが作成されます。このオブジェクトには、CronTrigger API オブジェクトの ID を返す getTriggerId メソッドがあります。

サンプルコード

このクラスは、進行中の商談のうち現在の日付までにクローズされているはずのものを照会し、所有者に商談を更新するよう通知する ToDo を各商談に作成します。

global class RemindOpptyOwners implements Schedulable {
    global void execute(SchedulableContext ctx) {
        List<Opportunity> opptys = [SELECT Id, Name, OwnerId, CloseDate
            FROM Opportunity
            WHERE IsClosed = False AND
            CloseDate < TODAY];
        // Create a task for each opportunity in the list
        TaskUtils.remindOwners(opptys);
    }
}

実行するクラスはプログラムを使用して、または Apex スケジューラ UI からスケジュールできます。

System.Schedule メソッドの使用

Schedulable インターフェースでクラスを実装したら、System.Schedule メソッドを使用してそれを実行します。System.Schedule メソッドはすべてのスケジュールの基盤としてユーザのタイムゾーンを使用しますが、システムモードで実行されます。つまり、ユーザにそのクラスの実行権限があるかどうかにかかわらず、すべてのクラスが実行されます。

メモ

メモ

クラスをトリガからスケジュールする場合は、細心の注意を払ってください。制限を超えるスケジュール済みジョブクラスをトリガで追加しないようにする必要があります。特に、API の一括更新、インポートウィザード、ユーザインターフェースを使用したレコードの一括変更、および複数のレコードを一度に更新するすべての処理については十分に考慮してください。

System.Schedule メソッドは、ジョブの名前、ジョブの実行予定日時を表すために使用する CRON 式、クラスの名前という 3 つの引数を取ります。

RemindOpptyOwners reminder = new RemindOpptyOwners();
// Seconds Minutes Hours Day_of_month Month Day_of_week optional_year
String sch = '20 30 8 10 2 ?';
String jobID = System.schedule('Remind Opp Owners', sch, reminder);

スケジュールに使用する Cron 式 についての詳細は、「Apex スケジューラ」の「System.Schedule メソッドの使用」を参照してください。

UI からのジョブのスケジュール

ユーザインターフェースを使用してクラスをスケジュールすることもできます。
  1. [設定] から、[クイック検索] ボックスに「Apex」と入力し、[Apex クラス] を選択します。
  2. [Apex をスケジュール] をクリックします。
  3. ジョブ名に「Daily Oppty Reminder」などと入力します。
  4. Apex クラスの横にあるルックアップボタンをクリックし、検索語に「*」と入力して、スケジュール可能なすべてのクラスのリストを取得します。検索結果で、スケジュール済みクラスの名前をクリックします。
  5. [毎週] または [毎月] の頻度を選択して、必要な頻度を設定します。
  6. 開始日と終了日、適切な開始時刻を選択します。
  7. [保存] をクリックします。

スケジュール済み Apex のテスト

これまでに説明した他の非同期メソッドと同様に、スケジュール済み Apex を使用する場合は、結果をテストする前にスケジュール済みジョブが終了していることを確認する必要があります。この確認には、System.schedule メソッドの前後に startTest と stopTest を再度使用して、テストを続行する前に処理が終了するようにします。

@isTest
private class RemindOppyOwnersTest {
    // Dummy CRON expression: midnight on March 15.
    // Because this is a test, job executes
    // immediately after Test.stopTest().
    public static String CRON_EXP = '0 0 0 15 3 ? 2022';
    static testmethod void testScheduledJob() {
        // Create some out of date Opportunity records
        List<Opportunity> opptys = new List<Opportunity>();
        Date closeDate = Date.today().addDays(-7);
        for (Integer i=0; i<10; i++) {
            Opportunity o = new Opportunity(
                Name = 'Opportunity ' + i,
                CloseDate = closeDate,
                StageName = 'Prospecting'
            );
            opptys.add(o);
        }
        insert opptys;
        // Get the IDs of the opportunities we just inserted
        Map<Id, Opportunity> opptyMap = new Map<Id, Opportunity>(opptys);
        List<Id> opptyIds = new List<Id>(opptyMap.keySet());
        Test.startTest();
        // Schedule the test job
        String jobId = System.schedule('ScheduledApexTest',
            CRON_EXP,
            new RemindOpptyOwners());
        // Verify the scheduled job has not run yet.
        List<Task> lt = [SELECT Id
            FROM Task
            WHERE WhatId IN :opptyIds];
        System.assertEquals(0, lt.size(), 'Tasks exist before job has run');
        // Stopping the test will run the job synchronously
        Test.stopTest();
        // Now that the scheduled job has executed,
        // check that our tasks were created
        lt = [SELECT Id
            FROM Task
            WHERE WhatId IN :opptyIds];
        System.assertEquals(opptyIds.size(),
            lt.size(),
            'Tasks were not created');
    }
}

留意事項

スケジュール済み Apex には注意すべき点がたくさんありますが、一般的な事項は次のとおりです (時間があるときに「リソース」セクションの「Apex スケジューラ」で完全なリストを確認してください)。
  • スケジュール済み Apex ジョブは一度に 100 件しか設定できず、スケジュール済み Apex の 24 時間あたりの最大実行数も制限されています。詳細は、「リソース」セクションの「実行ガバナと制限」を参照してください。
  • クラスをトリガからスケジュールする場合は、細心の注意を払ってください。制限を超えるスケジュール済みジョブをトリガで追加しないようにする必要があります。
  • 同期 Web サービスコールアウトは、スケジュールされた Apex からは実行できません。コールアウトを実行するには、@future(callout=true) のアノテーションを付加したメソッドにコールアウトを配置し、このメソッドをスケジュールされた Apex からコールすることで非同期コールアウトを実行します。ただし、スケジュールされた Apex で一括処理ジョブを実行する場合、一括処理クラスからコールアウトを実行できます。

リソース

メモ

メモ

このモジュールは Salesforce Classic 向けです。ハンズオン組織を起動するときには、Salesforce Classic に切り替えてから、この Challenge を実行してください。

無料で学習を続けましょう!
続けるにはアカウントにサインアップしてください。
サインアップすると次のような機能が利用できるようになります。
  • 各自のキャリア目標に合わせてパーソナライズされたおすすめが表示される
  • ハンズオン Challenge やテストでスキルを練習できる
  • 進捗状況を追跡して上司と共有できる
  • メンターやキャリアチャンスと繋がることができる