Apexを使った1日に複数回動作させるバッチ処理

セールスフォース

 Salesforceでバッチ処理を作成する方法としてはフロー処理の中の「スケジュールトリガーフロー」を使ってフロー処理として記述することが可能ですが、フローを動作させる頻度が「1回のみ、毎日、毎週」しかなく、1時間ごとに動作させるような設定ができません。

 今回は、10分ごとに処理を行うための実装をApexを使って行います。

1.バッチクラスとスケジュールクラス

 スケジュールの開始はスケジュールクラスを継承したクラスで実施し、この中からバッチクラスを呼び出し、バッチを実行します。

1.1 バッチクラスの作成

 バッチクラスを実装するためにはバッチクラスをインプリメントする必要があります。

 public class xxxxBatch implements Database.Batchable<sObject>,Database.Stateful { ....

 また以下のメソッドを実装する必要があります。

  
/* バッチ処理開始時に最初に呼び出される。バッチ処理対象となるレコードを返却するQueryLocatorを返す。*/ 
public Database.QueryLocator start(Database.BatchableContext bc) {
       処理
       return Database.getQueryLocator(xxxxx);
}
/* バッチサイズで指定されたレコード数の単位で、呼び出される。*/
public void execute(Database.BatchableContext bc,List<sObject> executeRecords) {                   
       処理
}
/* バッチ処理の終了時に呼び出される。終了処理があれば実装する */
public void finish(Database.BatchableContext bc) {
       処理
}

 それぞれのメソッドの記述内容は以下の様になります。

 startメソッドでは、DBの情報を取得するためのQueryを作成しそれを返却します。

public Database.QueryLocator start(Database.BachableContext bc) {
           string query = 'select XXXX from YYYY';           return Database.getQuery(query);
}

 startメソッドの終了後、executeメソッドが呼び出されます。その際startの返却値であるQueryが実行され、その結果がexecuteメソッドの第二引数に渡され、executeメソッドが呼び出されます。
 executeメソッドでは主たる処理を記述します。

public void execute(Database.BatchableContext bc,List(sObject> executeRecords) {
       ......
       for(hoge xx : executeRecords) {
          .........
       }
       .......
}

 executeメソッドに引き渡されたQeryの実行結果を順に取り出して処理を実施します。
 executeメソッドでExceptionが発生した場合、このトランザクションで実行されたものがロールバックされてしまいます。そのため、この処理の中でメール送信などを行っている場合にはメールを送信する処理もトランザクションの一部となるためメールが送信されないことになります。
 そのためtry~catch()を使用してExceptionを捕まえて処理することが必要となります。
 最後にfinishメソッドが実行されます。今回はこのfinishメソッド中で次のスケジュールを設定します。

public void finish(Database.BatchableContext bc) {
       DateTime nextSchedTime = DateTime.now().addMinutes(10);
       xxxxBatchSchedule cls = new xxxxBactchSchedule();
       String nextJobName = 'xxxBatchSchedule_'+nextSchedTime.format('yyyyNNddHHmm');
       String schd = nextSchedTime.format('0 m H d M ? yyyy');
       System.schedule(nextJobName,schd,cls);
}

 スケジュール設定について簡単な説明を以下に記載します。

DateTime nextSchedTime = DateTime.now().addMinutes(10);

 次にバッチを起動する時間を設定しています。10分毎にバッチ処理を実施するため、現在時間にaddMinutes()メソッドをつかって10分を加算し、次にバッチ処理を起動する時間を算出しています。

  xxxxBatchSchedule cls = new xxxxBactchSchedule();

 次節で説明するスケジューラクラスをインスタンス化しています。

  String nextJobName = 'xxxBatchSchedule_'+nextSchedTime.format('yyyyNNddHHmm');
  String schd = nextSchedTime.format('0 m H d M ? yyyy');

System.scheduleメソッドに渡すための、スケジュール名と、スケジュール設定する時間を作成しています。スケジュール名は一意でないといけないので、スケジュール時間を付加しています。

System.schedule(nextJobName,schd,cls);

スケジュール設定を行っています。

1.2 スケジュールクラスの作成

 スケジュールクラスでは、Schedulableをimprementします。またスケジュール済のパスが同時に処理できるレコードの数を指定します。デフォルトおよび最大値は200となっています。

 バッチサイズについては分単位、バッチ処理、および制限の強化によるスケジュール済みパスのパワーアップを参照してください。

public class xxxxBactchSchedule imprements Schedulable{
       private final Intefer BATCH_SIZE = 100;
       public xxxxBatchSchedule() {
 
       }
       public void execute(SchedulableContext sc) {
              xxxxBatch bt = new xxxxBatch();
              Database.executeBatch(bt,BATCH_SIZE);
       }
}

 Schedulableクラスのinprementsではexecuteメソッドを実装する必要があります。このexecuteメソッドはglobalまたはpublicで宣言する必要があります。
 executeメソッドの中でインスタンス化されているのは前節で定義したバッチクラスです。

2.Apexスケジューラの設定

 作成したスケジューラを起動するために、Apexスケジューラを設定します。

(1)Apexをスケジュール

 1.ホームタブをクリックし、検索窓からApexを検索します。
2.検索結果のカスタムコードのApexクラスをクリックします。
 3.「Apexをスケジュール」をクリックする

Apexをスケジュールを選択
図1 Apexをスケジュールを選択

(2)スケジュールを設定

スケジュール設定
図2 スケジュール設定

 1.ジョブ名:スケジュールジョブ名を設定
 2.Apexクラス:上記で作成したスケジュールクラス(xxxxBatchSchedule)を指定
 3.頻度、開始日時、終了日時、希望開始時刻を設定する

 注意事項
 1.頻度は、「毎週」または「毎月」しか選択できません。終了日までは指定した頻度でスケジュールが実行されます。上記のスケジュールクラスで設定した時刻とは異なるタイミングでバッチが起動される場合があります。そのため、スケジュールが重複設定されないように、頻度、終了日の設定を行う必要があります。
 2.ジョブキューの状況によっては、指定した日時時刻でのジョブ起動がされない場合があります。

3.スケジュール済のジョブの確認

 バッチクラス(xxxxBatch)で設定したスケジュールは、「設定」→「スケジュール済みジョブ」で確認することができます。

スケジュール済みジョブを確認する方法
図3. スケジュール済みジョブの確認

 アクションに「Manage」と表示されている場合、これをクリックすると起点となったスケジュールの詳細を見ることができます。

スケジュールの詳細表示
図4. スケジュールの詳細表示

 スケジュールを停止する場合には最新のスケジュールの削除アクションをクリックしてスケジュールを削除する必要があります。あわせて、起点となったスケジュールが定期的に実行されるように設定されているためこれも削除する必要があります。

 SFDCのスケジュールに関してはApex スケジューラを参照してください。

 

Apexを使った簡単なメール送信方法

セールスフォース

 SFDCからメールを送信する方法は色々とありますが、今回はApexを使った簡単なメール送信方法を紹介します。

 Apexコードを使用するとApexトリガーやApexスケジューラからメールを送信することができます。
 Apexからメール送信する方法には「単一メール送信」と「一括メール送信」があります。今回は「単一メール送信」を使った方法を説明します。
 さらにメール本体についてはApexの中でメール本体を作成する方法と「メールテンプレート」を使う方法がありますが、ここではメール本体をApexの中で作成します。

1.メールアドレス保存用カスタムオブジェクトの作成

 メール送信先を登録するための以下のようなカスタムオブジェクト(MailMember)を作成します。

カスタムオブジェクト(メールメンバー)
図1 カスタムオブジェクト(MailMember)

2.Apexでのメール作成と送信

 Apexでメールを作成し、送信する部分のコードは以下となります。

List<String>mailAdderList = new List<String>();

String mailMsg = '連絡事項';

List<MailMember__c>mailMember = [select id,Name,mailAddress__c from MailMember__c];
for(MailMember__c mM:mailMember){
  mailAdderList.add(mM.mailAddress__c);
  mailMsg += '\n';
  mailMsg += nM.name;
}
mailMsg += '\n';
mailMsg += 'メッセージを入力';

Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();

mail.setToAddresses(mailAdderList);
mail.setSubject('Test Mail Subject');
mail.setPlainTextBody(mailMessage);
mail.setUseSignature(false);
mail.setBccSender(false);
mail.setSenderDisplayName('メール送信者名入力');

List<Messaging.SendEmailResult> results = 
  Messaging.sendEmail(new List<Messaging.SingleEmailMessage>{mail},false);
for (Messaging.SendEmailResult result : results) {
    if (!result.isSuccess()) {
        System.debug(LoggingLevel.ERROR, result.getErrors()[0]);
    }
}

 コードの簡単な説明です。

 List<mailMember__c>mailMemberで送信先メールアドレスを保存します。

 new Messaging.SingleEmailMessage()により「単一メール送信」のインスタンスを作成します。

 mail.setToAddresses()にて送信先アドレスを設定します。設定できるアドレスは100件までです。

 mail.setSubject()にてメールサブジェクトを設定します。

 メール本体(メールのBody部)はmail.setPlainTextBody()にて作成します。

 メールの署名とBccは不要なので、setUseSignature()/setBccSender()にfalseを設定します。

 mail.setSenderDisplayName()でFrom行に表示される送信者表示名を設定します。   setOrgWideEmailAddressId()で組織の送信元のアドレスIDを設定した場合には設定できません。

 また、setOrgWideEmailAddressId()で添付ファイルをsetOrgWideEmailAddressId()で返信先メールアドレスを設定することができます。

 最後に、Messaging.sendEmail()でメールを送信します。2つ目の引数の指定は省略可能でデフォルトはtrueです。trueの場合、任意のsendEmailで失敗した場合、その他すべてのメッセージを送信しない、falseの場合は、メッセージを送信します。
 このメソッドはApex トランザクションごとに 10 回コールすることができます。

 Messaging.sendEmail()の結果はList<Messaging.SendEmailResult> resultsで受け取ることができます。配列で返却された結果に対してisSuccess()メソッドを実施することで結果を取得することができます。isSuccess()の結果がfalseの場合、getError()を使い、sendEmailErrorオブジェクトを取得することができます。エラーとなるのは送信時のエラーで、送信先に到達したか否かは関係ありません。

3.NO_MASS_MAIL_PERMISSIONエラー

 メール送信を実行した場合に「NO_MASS_MAIL_PERMISSION」というエラーが出る場合があります。これは「メールを送信するためのアクセス権」がない場合に発生します。設定により、権限を「すべてのメール」に変更します。

1.検索窓で「送信」を入力
2.メールメニューの「送信」を選択

図2 メールのアクセス権の設定(1)
【図2 メールのアクセス権の設定(1)】

3.アクセス権で「すべてのメール」を選択

図3 メールのアクセス権の設定(2)
【図3 メールのアクセス権の設定(2)】
【図4】メールのアクセス権の設定(3)
【図4】メールのアクセス権の設定(3)

本番組織の開発者コンソールは何ができるかやってみた

Salesforceでやってみた

はじめに

こんにちは!株式会社オプトプランニングです。
他業種から転職し、右も左もわからない新人社員がSalesforceを使ってあれこれしてみる様子を書いていこうと思います。

今回はSalesforce本番組織の開発者コンソールは何ができるのかやってみたいと思います。

開発者コンソールとは

開発者コンソールとは、Salesforceが提供する一連のツールを備えた総合開発環境です。
Webベースの開発環境なのでインストールなどの事前準備が不要で、Salesforce組織のアプリケーションの作成やデバッグ、テストなど様々な事が行えます。

そんな開発者コンソールですが、基本的には開発環境であるSandbox上で使用していると思います。
ですが、本番組織でも開発者コンソールを開くことができます。
本番組織とSandboxでできる事の違いがあるのか、違いがあればどんなところかを実際にやってみたいと思います。

本番組織の開発者コンソール

開発者コンソールを開いてみた

本番組織とSandboxで開発者コンソールの開き方に違いはありません。

「⚙」アイコンをクリックすると表示されるポップアップ内にある「開発者コンソール」をクリックすると開発者コンソールは開きます。

ここで「開発者コンソール」が表示されない場合は必要な権限設定が行われていないからかもしれません。
必要権限としては、システム権限の内

  • APIの有効化
  • すべてのデータの参照

の二つです。
この2つが有効になっていないユーザで操作している場合、開発者コンソールの表示はされないので注意してください。

図1 本番組織「⚙」押下後
図1 本番組織「⚙」押下後
図2 Sandbox「⚙」押下後
図2 Sandbox「⚙」押下後

早速、本番組織で開発者コンソールを開いてみましたが、Sandboxで開いた時と違いはありませんでした。

Salesforceにログインした時、Sandboxだと画面上部にSandbox名が表示されますが、そういったものもありません。
違いがなさ過ぎて、同時に開くとどっちがどっちかわからなくなってしまいそうです。

開発者コンソールは別ブラウザで開くので、別組織のものは同時に開かない方がよさそうですね。

図3 本番組織の開発者コンソール
図4 Sandboxの開発者コンソール

Apexを編集してみた

開発者コンソールを無事に開けたので、次は本番組織内にあるApexのファイルを開いて編集してみようと思います。
この時、システム権限として

  • Apex開発

が有効になっているユーザで操作しています。

そもそもApexのファイルを開けるかですが、こちらは問題なく開けました。

編集もできるか試してみます。
赤枠部分をコメントアウトしてみました。

赤枠部分のコメントアウトをすることができました。

次に、編集した内容をSaveしてみますが…

このようなエラーが出てしまいました…

Deployment Failed
Can’t alter metadata in an active org

何度か「Save」を試してみたところ、最初は「Save」をクリックした後エラーが出ていましたが、「Save」をクリックする前から表示されるようになってしまいました。

本番組織ではApexの編集を保存することはできません。

Apexクラスを変更したい時、Salesforce上だけで完結させるためには、Sandbox環境で編集を行い、本番環境に向けて変更セットをアップロード&リリースするしかなさそうです。

ちょっとした変更も例外なく変更セットを使用しなければならない点は要注意です。

クエリエディタを使ってみた

Apexの保存はできませんでしたが、開発者コンソールを開けるということは何かできるはず…

ということで、次はクエリエディタでSOQLクエリの実行を試してみます。

取引先のIDとNameを検索してみましたが、問題なく実行することができました!
本番組織上のデータの検索を行うことはできそうです。

あとがき

今回は本番環境の開発者コンソールでApexの編集とクエリエディタの使用をやってみました。

開発者コンソールは基本的にSandboxで使用するものという位置づけのようなので、本番環境からの使用はあまり期待しないほうがよさそうです。

他の機能についても、今後やってみたで検証できればと思います。

では、またお会いしましょう!!