Skip to main content
Tableau Conference is live on Salesforce+. Stream it free — watch now.

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

学習の目的

この単元を完了すると、次のことを理解できるようになります。

  • スケジュール済み Apex を使用するケース。
  • スケジュール済みジョブを監視する方法。
  • スケジュール済み Apex の構文。
  • scheduled メソッドのベストプラクティス。
メモ

メモ

日本語で受講されている方へ
Challenge は日本語の Trailhead Playground で開始し、かっこ内の翻訳を参照しながら進めていってください。Challenge での評価は英語データを対象に行われるため、英語の値のみをコピーして貼り付けるようにしてください。日本語の組織で Challenge が不合格だった場合は、(1) この手順に従って [Locale (地域)] を [United States (米国)] に切り替え、(2) [Language (言語)] を [English (英語)] に切り替えてから、(3) [Check Challenge (Challenge を確認)] ボタンをクリックしてみることをお勧めします。

翻訳版 Trailhead を活用する方法の詳細は、自分の言語の Trailhead バッジを参照してください。

一緒にトレイルを進みましょう

インストラクターと一緒にこの手順を進めますか? 次の動画をご覧ください。これは Trailhead Live の「Trail Together (一緒にトレイル)」シリーズの一部です。

(この動画は 1:09:53 の時点から始まります。戻して手順の最初から見直す場合はご注意ください。)

スケジュール済みの Apex

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

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

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

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

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

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

サンプルコード

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

public with sharing class RemindOpptyOwners implements Schedulable {
  public void execute(SchedulableContext ctx) {
    List<Opportunity> opptys = [
      SELECT Id, Name, OwnerId, CloseDate
      FROM Opportunity
      WHERE IsClosed = FALSE AND CloseDate < TODAY
      WITH USER_MODE
    ];
    // Create a task for each opportunity in the list
    List<Task> tasks = new List<Task>();
    for (Opportunity opp : opptys) {
      Task newTask = new Task(
        Subject = 'Update the Opportunity!',
        Priority = 'Normal',
        Status = 'Not Started',
        WhatId = opp.Id
      );
      tasks.add(newTask);
    }
    insert as user tasks;
  }
}



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

System.Schedule メソッドの使用

Schedulable インターフェースを使用してクラスを実装したら、System.schedule() メソッドを使用してこのクラスを実行します。System.schedule() メソッドはすべてのスケジュールの基盤としてユーザーのタイムゾーンを使用します。

Note

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

System.schedule() メソッドは、ジョブの名前、ジョブの実行予定日時を表すために使用する CRON 式、Schedulable インターフェースを実装するクラスのインスタンスという 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. [Setup (設定)] から、[Quick Find (クイック検索)] ボックスに Jobs (ジョブ) と入力し、[Scheduled Jobs (スケジュール済みジョブ)] を選択します。
  2. [Apex をスケジュール] をクリックします。
  3. ジョブ名に Daily Oppty Reminder などと入力します。
  4. Apex クラスの横にあるルックアップボタンをクリックし、検索語に*と入力して、スケジュール可能なすべてのクラスのリストを取得します。検索結果で、スケジュール済みクラスの名前をクリックします。
  5. Weekly (毎週)またはMonthly (毎月)の頻度を選択して、必要な頻度を設定します。
  6. 開始日と終了日、適切な開始時刻を選択します。
  7. [Save (保存)] をクリックします。

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

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

@IsTest
private with sharing class RemindOppyOwnersTest {
  // Placeholder CRON expression: midnight on March 15.
  // Because this is a test, job executes
  // immediately after Test.stopTest(), not at the time set in the CRON expression
  public static String CRON_EXP = '0 0 0 15 3 ? 2042';


  @IsTest
  static 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 as user 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
      WITH USER_MODE
    ];
    Assert.areEqual(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
      WITH USER_MODE
    ];
    Assert.areEqual(opptyIds.size(), lt.size(), 'Tasks were not created');


    // Check the scheduled time
    List<CronTrigger> ct = [
      SELECT Id, TimesTriggered, NextFireTime
      FROM CronTrigger
      WHERE Id = :jobId
      WITH USER_MODE
    ];
    System.debug('Next Fire Time ' + ct[0].NextFireTime);
  }
}

留意事項

スケジュール済み Apex には注意すべき点がたくさんありますが、一般的な事項は次のとおりです (時間があるときに「Apex スケジューラー」で完全なリストを確認してください)。

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

リソース

Salesforce ヘルプで Trailhead のフィードバックを共有してください。

Trailhead についての感想をお聞かせください。[Salesforce ヘルプ] サイトから新しいフィードバックフォームにいつでもアクセスできるようになりました。

詳細はこちら フィードバックの共有に進む