2022.08.19

スケジュール済みApexを更新できるようにする方法

はじめに

こんにちは。
この記事では、スケジュール済みにしたApexクラスで、スケジュールを停止せずに処理クラスの内容を更新する方法を紹介します。
処理クラスを更新する際に、スケジュールを一度解除してから、再登録する場合、どのユーザを実行者にするのか、どのような方法で登録するのか、と懸念事項が増えます。
しかし、クラスを一つ加えることで更新が可能になるので、これからApexでのバッチ機能を考えている方には、ぜひ本記事を参考にしていただければと思います。

スケジュール済みのApexは更新できない?

まず、本記事の前提になりますが、一度スケジュール登録をしたApexは編集/更新ができず、関連するクラスも全て編集/更新ができなくなります。変更セットやパッケージのアップデートを通して更新する際も更新ができません。

↑スケジュールクラスから実行する処理クラス「SampleBatch」の変更内容を保存できない。
Salesforceでは、Apexクラスがスケジュールされた時に新しいインスタンスを作成する仕様になっているので、スケジュールされた後に更新ができないのです。

クラスの構成を変える

どのようにすれば更新不可を回避できるのでしょうか。
上記の仕様を考えると、新しいインスタンスを作成するタイミングを変えることで実現できるはずです。
そこで、スケジュール登録をするスケジュールクラスは単なるラッパーとし、追加クラスのインスタンスを作成する二重の構造にすれば、Salesforceのスケジュール登録に左右されなくなると考えられます。
public class SampleBatchSchedule implements Schedulable {
  final Integer BATCH_SIZE = 1;
    
  public void execute(SchedulableContext sc) {
      SampleBatch batch = new SampleBatch();
      Database.executeBatch(batch, BATCH_SIZE);     
  }
}
よくあるスケジュールクラス
上記はよくあるスケジュールクラスです。
バッチサイズを指定し、処理クラスを実行させます。
この内容は、追加するクラス「CalledByBatchSchedule」に移動させます。
public class CalledBySampleBatchSchedule implements SampleBatchSchedule.IScheduler{
    final Integer BATCH_SIZE = 1;

    public void execute(SchedulableContext sc) {
        SampleBatch batch = new SampleBatch();
        Database.executeBatch(batch, BATCH_SIZE);
    }
}
追加クラス「CalledBySampleBatchSchedule」

本スケジュールクラスでインターフェイスを定義する

追加したクラスで、インターフェイス「IScheduler」が埋め込まれているのに気付いたでしょうか。
時間指定でApexクラスを呼び出すには、インターフェイスSchedulableを実装しなくてはいけません。
したがって追加したクラスにも同じ機能を果たすインターフェイスが必要となります。
そこで、元々あったスケジュールクラス「SampleBatchSchedule」内で新しくインターフェイスを用意し、インターフェイスSchedulableのメソッドを使うようにし、追加クラスで実装させます。
public Interface IScheduler {
        void execute(SchedulableContext sc);
}
Schedulableのインターフェイスを定義

本スケジュールクラスで追加スケジュールクラスのインスタンスを作成する

それでは、最後に本スケジュールクラスでの処理を書きましょう。
処理クラスのインスタンスを作成しない代わりに、追加クラスのインスタンスを作成し、追加クラスから処理クラスが実行されるようにします。
public class SampleBatchSchedule implements Schedulable {
 
      public Interface IScheduler {
              void execute(SchedulableContext sc);
      }
    
      public void execute(SchedulableContext sc) {
      
              Type targetType = Type.forName('CalledBySampleBatchSchedule');
        
              if(targetType != null) {
                      IScheduler schedule = (IScheduler)targetType.NewInstance();
                      schedule.execute(sc);
              }
      }
}
本スケジュールクラス「SampleBatchSchedule」
追加クラスのインスタンスを作成するには、ApexにあるTypeクラスを使用します。
Typeクラスは、Apex クラスによって実装されているインターフェイス(ここではIScheduleer)のメソッドを動的に呼び出す場合に必要となります。
TypeクラスのforNameメソッドでは、追加スケジュールクラス「CalledBySampleBatchSchedule」のデータ型を取得します。
続いて、NewInstanceメソッドでは、先ほど取得した追加スケジュールクラスのデータ型のインスタンスを作成し、返します。
これで完了です。
初めに、更新できなかったクラス「SampleBatch」更新できるようになります。

また、Typeクラスについて詳細はこちらを参照してください。
https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_methods_system_type.htm

さいごに

今回は、Apexのスケジュールについて焦点をあてました。
インターフェイスの仕組みやApexでの使い方をじっくりと調べると非常に面白いかと思います。
21 件
     
  • banner
  • banner

関連する記事