Blogical

AWS/Salesforceを中心に様々な情報を配信していきます(/・ω・)/

プロセスビルダーからApexクラスを呼び出す

こんにちは、ロジカルアーツの岸谷です。

Salesforceのプロセスビルダーはあるオブジェクトの作成時や更新時の項目の値などをもとに、他の項目の値を更新することができます。

また、オブジェクトの項目設定だけではなくApexクラスを呼ぶこともできるので、外部のWebサービスを呼ぶなど、もう少し複雑なビジネスロジックを処理したい場合も重宝します。

今回はその中でも、プロセスビルダーからApexクラスを呼び出す際のApexクラス、プロセスビルダー、ならびにテストクラスの作成について学んだことをまとめていきたいと思います。

概要

プロセスビルダーからApexクラスを呼び出すには、InvocableMethodアノテーションを宣言することで可能になります。

プロセスビルダーから値を受け取る場合はList型の引数を使って受け取るようになっていますが、InvocableVariableアノテーションを利用することで直接変数に値をセットすることもできます。

Apexクラスの作成

InvacableMethodアノテーション

初めに、呼ばれる側のApexクラスを作成します。

プロセスビルダーから呼び出すApexクラスのメソッドにこのアノテーションを付けることにより、フローやプロセスビルダーから呼び出すことが可能になります。

※InvacableMethodアノテーションの考慮事項について(詳しくは参考サイトの"Salesforce Developer"を参考にしてください)
・呼び出し可能なメソッドは、staticで、publicまたはglobalである必要があり、そのクラスは外部クラスである必要があります。
・InvocableMethodアノテーションをつけたメソッドは、クラスの1つのメソッドのみ宣言可能となります。なので、アクション毎にクラスを作成する必要があります。
・他のアノテーションと併用することはできません。
・引数は必ずリスト型にする必要があります。

// 処理クラス
global class CalledClassFromProcess{
    @invocableMethod(label='XXXX')//任意のラベル名をつける
    global static void sampleMethod(List<String> rfpList){ 
     //処理を記載
    String rfp = rfpList[0];
    }
}

“label”は、InvocableMethodアノテーションのついたメソッドをプロセスビルダーから呼び出すときに利用します。

ここで注意すべきなのが、InvocableMethodアノテーションをつけたメソッドは、引数を1つだけしか設定できないことです。
試しにプロセスビルダーから複数の引数を渡すと、

// 処理クラス
global class CalledClassFromProcess{
    @invocableMethod(label='XXXX')//任意のラベル名をつける
    global static void sampleMethod(List<String> rfpList, List<String> rfp2List){ 
     String rfp = rfpList[0];
     String rfp2 = rfp2List[0];
    }
}

以下のエラーが出ます。

Only one parameter is supported on methods with @Invocable annotation

InvocableMethodアノテーションをつけたメソッドに対して一つしか引数をとれないのはわかったけれど、複数の引数を渡したい!…こういったときに使うのが”InvocableVariable”アノテーションです。
このアノテーションを用いて引数をまとめたクラスを作ることで、複数の引数を渡すことができるようになります。

InvocableVariableアノテーション

InvocableVariableアノテーションを使って、上記のApexコードを以下のように変えてみます。
※〇〇レコード(下記Apexコード参照)のIdは必須項目ですので、指定し忘れのないように注意してください。  もう一つの”user”(使用者を取得するための変数として使用)は必須ではありませんが、複数のパラメータを渡す例として記述しています。必要に応じて書き換えてください。

// 処理クラス
global class CalledClassFromProcess{

    @invocableMethod(label='XXXX')//任意のラベル名をつける
    global static void sampleMethod(List<ReceivedFromProcess> rfpList){ 
    ReceivedFromProcess rfp = rfpList[0];
        System.debug('ID='+rfp.sampleId);
        System.debug('User='+rfp.user);
    }
    
    // プロセスビルダーから値を受け取るためのラッパークラス
    global class ReceivedFromProcess{
        @invocableVariable
        public Id sampleId; //○○レコードのId
        @invocableVariable
        public Id user; 
    }
}

以上でApexクラス側の設定は終了です。
このクラスに記載したInvocableMethodアノテーション とInvocableVariableアノテーション の 2 つのアノテーションで、sampleMethodをプロセスビルダーに公開できます。

プロセスの作成

プロセスビルダーの設定を行い、上記のApexクラスをコールします。
プロセスビルダーを新規作成、Apexクラスを呼び出す任意の条件を設定した後、Apexクラスをコールするためのアクションを下記の通りに設定します。
これで、InvocableVariableアノテーションが付加されたパラメータを受け入れることができます。

  1. アクション種別:「Apex」
  2. アクション名:任意
  3. Apexクラス:上記@invocableMethodで指定したlabel名
  4. Apex変数を設定(⓵は必須、〇〇レコードのIdを渡す ②は任意、今回はuserを指定しているため追加。種別・値は任意の値に変更): 
      sampleId→
       項目:@InvocableVariableを指定した変数
       種別:項目の参照
       値 : 〇〇レコードのId
      user→
       項目:@InvocableVariableを指定した変数
       種別:項目の参照
       値 : レコードに変更を加えたときに、Apexクラスを呼び出す起点となる値(今回は"user") f:id:logicalarts:20200605112130p:plain

該当オブジェクトのレコードを、プロセスビルダーで設定した条件をもとに更新してみましょう。 これで、設定したプロセスが動き、Apexクラスが呼ばれます。

開発者コンソールでログを見てみると、レコードIDと使用者を取得できていることが分かります。

USER_DEBUG [7]|DEBUG|ID=a002v00004HnrCmAAJ

USER_DEBUG [8]|DEBUG|User=a032v00004VjYFIAA3

テストクラス内で処理クラスのメソッドを呼ぶ

次にテストクラスでの処理の記述についてですが、その前に・・・
初めて本番環境にApexクラスと、そのApexを呼び出すプロセスビルダーをアップするときの注意点があります。

一つには、プロセスビルダーをアップすると自動的に無効化されていること。

二つには、プロセスビルダーからApexクラスを呼び出す機能に関して、本番環境にアップする際はプロセスビルダーとApexクラスを同時に上げる必要があること。

以上の事から、テストクラスでプロセスビルダーを呼んでテストを行うことは推奨しません。 その代わり、テストクラスの中で処理クラスのメソッドを呼ぶことでこれらの問題は解決できます。

それでは、テストクラスでの処理について記述していきます。

  1. Apexクラスに作成した、プロセスビルダーから値を受け取るためのラッパークラス(ReceivedFromProcess)にテストデータを渡すために、テストクラスにラッパークラスを作成する。
  2. そのラッパークラスのListに、作成したテストデータのIdを挿入する。
  3. 最後に、そのリストをApexクラスのInvocableMethodアノテーションを付与したメソッドに渡す。
// テストクラス
@isTest
public class CalledClassFromProcessTest {
    // テストデータ作成
  // 使用者レコード作成
     User__c user = new User__c();
         user.Name = '田中';
         insert user;
  //〇〇レコード作成(例:PCManagementオブジェクト)
     PCManagement__c pm = new PCManagement__c();
         pm.Place__c = '会議室A';
         pm.User__c = user.Id;
         insert pm;

    // ラッパークラス生成
    List<CalledClassFromProcess.ReceivedFromProcess> rfpList = new List<CalledClassFromProcess.ReceivedFromProcess>();

    // テストデータのIDをラッパークラスのリストに詰める
        CalledClassFromProcess.ReceivedFromProcess rfp = new CalledClassFromProcess.ReceivedFromProcess();
        rfp.sampleId = pm.Id;
        rfp.user= user.Id;  
        rfpList.add(rfp);
    
    // メソッド呼び出し
    CalledClassFromProcess.sampleMethod(rfpList);
}

このように処理を書くことで、プロセスビルダーなしでクラスをデプロイすることができます。

おわりに

いかがでしたでしょうか?
invocableMethodの引数など注意する点はいくつかありますが、これでプロセスビルダーとApexの連携技が使えるようになります。
テストクラスに関しては、上記処理を書く以外にも同API名のプロセスビルダーを先にアップしておいて…などの方法があるそうですが、こちらの手法の方が確実なようです。
本記事が少しでもお役に立てれば幸いです。

参考サイト

developer.salesforce.com

nodding-off-programmer.blogspot.com

ja.voidcc.com

web.plus-idea.net