Apex スケジューラーを使用したジョブのスケジュール
学習の目的
この単元を完了すると、次のことを理解できるようになります。
- スケジュール済み Apex を使用するケース。
- スケジュール済みジョブを監視する方法。
- スケジュール済み Apex の構文。
- scheduled メソッドのベストプラクティス。
一緒にトレイルを進みましょう
インストラクターと一緒にこの手順を進めますか? 次の動画をご覧ください。これは Trailhead Live の「Trail Together」(一緒にトレイル) シリーズの一部です。
(この動画は 1:09:53 の時点から始まります。戻して手順の最初から見直す場合はご注意ください。)
スケジュール済みの Apex
Apex スケジューラーを使用すると、Apex クラスの実行を遅らせて、指定した日時に実行できます。このスケジューラーは、Apex 一括処理を使用した日次または週次のメンテナンス作業に最適です。スケジューラーを活用するには、Schedulable インターフェースを実装する Apex クラスを記述して、特定のスケジュールで実行されるようにクラスをスケジュールします。
スケジュール済み Apex の構文
特定の時間に実行される Apex クラスを呼び出すには、まずクラスに Schedulable インターフェースを実装します。次に、System.schedule() メソッドを使用して、特定の時間に実行されるようにクラスのインスタンスをスケジュールします。
public class SomeClass implements Schedulable {
public void execute(SchedulableContext ctx) {
// awesome code here
}
}このクラスは Schedulable インターフェースを実装し、このインターフェースに含まれるメソッド (execute() メソッド) のみを実装する必要があります。
このメソッドのパラメーターは SchedulableContext オブジェクトです。クラスがスケジュールされると、スケジュール済みジョブを表す CronTrigger オブジェクトが作成されます。このオブジェクトには、CronTrigger API オブジェクトの ID を返す getTriggerId() メソッドがあります。
サンプルコード
このクラスは、進行中の商談のうち現在の日付までにクローズされているはずのものを照会し、所有者に商談を更新するよう通知する ToDo を各商談に作成します。
public 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];
// Create a task for each opportunity in the list
TaskUtils.remindOwners(opptys);
}
}実行するクラスはプログラムを使用して、または Apex スケジューラー UI からスケジュールできます。
System.Schedule メソッドの使用
Schedulable インターフェースを使用してクラスを実装したら、System.schedule() メソッドを使用してこのクラスを実行します。System.schedule() メソッドはすべてのスケジュールの基盤としてユーザーのタイムゾーンを使用しますが、システムモードで実行されます。つまり、ユーザーにそのクラスの実行権限があるかどうかにかかわらず、すべてのクラスが実行されます。
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 からのジョブのスケジュール
ユーザーインターフェースを使用してクラスをスケジュールすることもできます。
- [Setup (設定)] から、[Quick Find (クイック検索)] ボックスに
Apexと入力し、[Apex Classes (Apex クラス)] を選択します。 - [Apex をスケジュール] をクリックします。
- ジョブ名に
Daily Oppty Reminderなどと入力します。 - Apex クラスの横にあるルックアップボタンをクリックし、検索語に
*と入力して、スケジュール可能なすべてのクラスのリストを取得します。検索結果で、スケジュール済みクラスの名前をクリックします。 Weekly(毎週)またはMonthly(毎月)の頻度を選択して、必要な頻度を設定します。- 開始日と終了日、適切な開始時刻を選択します。
- [Save (保存)] をクリックします。
スケジュール済み 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 ? 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 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 で一括処理ジョブを実行する場合、一括処理クラスからコールアウトを実行できます。
リソース
