Apex アノテーション備忘録

#1.Apexアノテーション一覧
- [@AuraEnabled](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_AuraEnabled.htm)
- [@Deprecated](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_deprecated.htm)
- [@Future](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_future.htm)
- [@InvocableMethod](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_InvocableMethod.htm)
- [@InvocableVariable](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_InvocableVariable.htm)
- [@IsTest](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_isTest.htm)
- [@IsTest(SeeAllData=true)](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_isTest.htm)
- [@IsTest(OnInstall=true)](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_isTest.htm)
- [@IsTest(isParallel=true)](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_isTest.htm)
- [@ReadOnly](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_ReadOnly.htm)
- [@RemoteAction](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_RemoteAction.htm)
- [@SuppressWarnings](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_SuppressWarnings.htm)
- [@TestSetup](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_testsetup.htm)
- [@TestVisible](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_testvisible.htm)
- Apex REST アノテーション:
 - [@HttpGet](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_http_get.htm)：Read
 - [@HttpPost](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_http_post.htm)：Create
 - [@HttpPatch](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_http_patch.htm)：Update
 - [@HttpPut](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_http_put.htm)：Upsert
 - [@HttpDelete](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_http_delete.htm)：Delete*

#2.各アノテーション説明
**[@AuraEnabled](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_AuraEnabled.htm)**
---
**`【概要説明】`**
AuraEnabled アノテーションにより、Lightning コンポーネントから Apex メソッドおよびプロパティへのアクセスが可能になります。

**`【使用箇所】`**

- Apexクラスの静的メソッド
- Apex インスタンスのメソッドおよびプロパティ

**`【考慮事項】`**

- 実行時のパフォーマンスを改善するには、@AuraEnabled(cacheable=true) を設定してクライアントにメソッドの結果をキャッシュします。
- cacheable=true を設定するには、メソッドがデータのみを取得する必要があり、データを変更することはできません。

```java:使用例
public with sharing class SimpleAccountController {
    @AuraEnabled
    public static List<SimpleAccount> getAccounts() {
        List<SimpleAccount> simpleAccounts = new List<SimpleAccount>();
        List<Account> accounts = [SELECT Id, Name, Phone FROM Account LIMIT 5];
        for (Account acct : accounts) {
            simpleAccounts.add(new SimpleAccount(acct.Id, acct.Name, acct.Phone));
        }
        return simpleAccounts;
    }
}
``` 
```java:使用例(cacheable=true)
@AuraEnabled(cacheable=true)
public static Account getAccount(Id accountId) {
    // your code here
}
``` 
**[@Deprecated](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_deprecated.htm)**
---
**`【概要説明】`**
Apex関連のリソースを廃止されたことを示します。

**`【使用箇所】`**

- メソッド
- クラス
- 例外
- 列挙
- インターフェース
- 変数

**`【考慮事項】`**

- 非管理パッケージには、deprecated キーワードを使用するコードを含めることはできません。
- webservice メソッドおよび変数は廃止できません。
- enum は廃止できますが、各 enum 値は廃止できません。
- インターフェースは廃止できますが、インターフェースの各メソッドは廃止できません。
- 抽象クラスは廃止できますが、抽象クラスの各抽象メソッドは廃止できません。

```java:使用例
  @deprecated
  // This method is deprecated. Use myOptimizedMethod(String a, String b) instead.
  global void myMethod(String a) {}
``` 
**[@Future](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_future.htm)**
---
**`【概要説明】`**
メソッドの非同期実行

**`【使用箇所】`**
メソッド

**`【考慮事項】`**

- static void である必要あり。
- 引数はプリミティブ型、プリミティブ型の配列、プリミティブ型のコレクション
　 ※sObjectが渡せない理由：メソッドをコールしてからそのメソッドを実際に実行するまでの間にオブジェクトが変更される可能性があるためです。
- future メソッドから future メソッドをコールすることはできません。
- future メソッドはコールされた順序で実行されるとは限りません。

```java:使用例
public class SMSUtils {
    // Call async from triggers, etc, where callouts are not permitted.
    @future(callout=true)
    public static void sendSMSAsync(String fromNbr, String toNbr, String m) {
        String results = sendSMS(fromNbr, toNbr, m);
        System.debug(results);
    }

    // Call from controllers, etc, for immediate processing
    public static String sendSMS(String fromNbr, String toNbr, String m) {
        // Calling 'send' will result in a callout
        String results = SmsMessage.send(fromNbr, toNbr, m);
        insert new SMS_Log__c(to__c=toNbr, from__c=fromNbr, msg__c=results);
        return results;
    }
}
``` 
**[@InvocableMethod](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_InvocableMethod.htm)**
---
**`【概要説明】`**
フローやプロセスビルダーから呼ぶことが可能になります。

**`【使用箇所】`**
メソッド

**`【考慮事項】`**

- 呼び出し可能なメソッドは、static で、public または global である必要があり、そのクラスは外部クラスである必要があります。
- クラスの 1 つのメソッドにのみ InvocableMethod アノテーションを付加できます。
- 他のアノテーションと InvocableMethod アノテーションを併用することはできません。

```java:使用例
public class AccountInsertAction {
  @InvocableMethod(label='Insert Accounts' description='Inserts the accounts specified and returns the IDs of the new accounts.')
  public static List<ID> insertAccounts(List<Account> accounts) {
    Database.SaveResult[] results = Database.insert(accounts);
    List<ID> accountIds = new List<ID>();
    for (Database.SaveResult result : results) {
      if (result.isSuccess()) {
        accountIds.add(result.getId());
      }
    }
    return accountIds;
  }
}
``` 
**[@InvocableVariable](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_InvocableVariable.htm)**
---
**`【概要説明】`**
@InvocableMethodの入力パラメータまたは出力結果を定義します。

**3 つの修飾子**
　・label：変数の表示ラベル。デフォルトは変数名です。
　・description：変数の説明。デフォルトは Null です。
　・required：変数が必須かどうか。指定されていない場合のデフォルトはfalseです。出力変数ではこの値が無視されます。

**`【使用箇所】`**
メンバ変数

**`【考慮事項】`**

- 他のアノテーションと InvocableVariable アノテーションを併用することはできません。
- 呼び出し可能な変数にすることができるのは、グローバル変数と公開変数のみです。
- 次に該当する場合は、呼び出し可能な変数にできません。
  - interface、class、enum などの型
  - static 変数、local 変数などの非メンバー変数
  - プロパティ
  - final 変数
  - Protected または private
- 呼び出し可能な変数のデータ型は、次のいずれかである必要があります。
  - プリミティブデータ型、またはプリミティブデータ型のリスト – 汎用 Object 型はサポートされていません。
  - sObject 型、または sObject 型のリスト – 汎用 sObject 型はサポートされていません。

```java:使用例
global class XXXXXXInvocableAction {
    // フローやプロセスビルダーから呼び出し可能なメソッド
    @InvocableMethod
    global static List<Output> execute(List<Input> inputList) {
        List<Output> results = new List<Output>();
            // 業務処理
        }
        return results;
    }

    // 入力用クラス
    global class Input {
        @InvocableVariable(label='first name' description='your Description' required=true)
        global String firstName;

        @InvocableVariable(label='last name' description='your Description' required=true)
        global String lastName;
    }
  
     // 出力用クラス
    global class Output {
        @InvocableVariable
        global String fullName;

        @InvocableVariable
        global Integer index;
    }
}
``` 
**[@IsTest](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_isTest.htm)**
---
**`【概要説明】`**
テストコードを宣言するアノテーション。

**`【使用箇所】`**
クラスorメソッド

**`【考慮事項】`**

- testMethod キーワードは非推奨になりました。クラスやメソッドには代わりに@isTest アノテーションを使用します。
- @isTest アノテーションで指定されたクラスは、Apexコードの組織内の上限の6MBには含まれません。
- クラスにつけた場合は組織のコードにカウントされず、メソッドにつけた場合は、TesRunでテストを走らせることができます。
- @isTest として定義されたクラスは、インターフェースまたは列挙値とすることはできません。
- 公開テストクラスのメソッドは、実行中のテスト、つまり、テストメソッドまたはテストメソッドから呼び出されるコードからのみコールすることができます。公開メソッドは、テスト以外の要求からコールすることはできません。

```java:非公開テストクラスの例
@isTest
private class MyTestClass {
   // Methods for testing
   @isTest static void test1() {
      // Implement test code
   }

   @isTest static void test2() {
      // Implement test code
   }
}
``` 
```java:公開テストクラスの例
@isTest 
public class TestUtil {
   public static void createTestAccounts() { 
      // Create some test accounts
   }

   public static void createTestContacts() {
      // Create some test contacts
   }
}
``` 
**[@IsTest(SeeAllData=true)](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_isTest.htm)**
---
**`【概要説明】`**
組織のデータを使用するか否かのオブション。
SeeAllData=trueで組織に登録されているデータを使用することができます。

**`【使用箇所】`**
クラス or メソッド

**`【考慮事項】`**
@isTest(SeeAllData=false) により、@isTest(SeeAllData=true)の定義は優先されます。

```java:使用例
// All test methods in this class can access all data.
@isTest(SeeAllData=true)
public class TestDataAccessClass {
    // This test accesses an existing account. 
    // It also creates and accesses a new test account.
    static testmethod void myTestMethod1() {
        // Query an existing account in the organization. 
        Account a = [SELECT Id, Name FROM Account WHERE Name='Acme' LIMIT 1];
        System.assert(a != null);
        
        // Create a test account based on the queried account.
        Account testAccount = a.clone();
        testAccount.Name = 'Acme Test';
        insert testAccount;
        
        // Query the test account that was inserted.
        Account testAccount2 = [SELECT Id, Name FROM Account 
                                WHERE Name='Acme Test' LIMIT 1];
        System.assert(testAccount2 != null);
    }
    
    // Like the previous method, this test method can also access all data
    // because the containing class is annotated with @isTest(SeeAllData=true).
    @isTest static void myTestMethod2() {
        // Can access all data in the organization.
   }
}
```
**[@IsTest(OnInstall=true)](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_isTest.htm)**
---
**`【概要説明】`**
パッケージのインストール時に実行されるオプションです。

**`【使用箇所】`**
クラスorメソッド

**`【考慮事項】`**

- パッケージインストール時にこのテストが失敗するとインストールができません。
- このアノテーションは、管理パッケージまたは未管理パッケージのテストで使用されます。

```java:使用例
@isTest
private class OnInstallClassTest {
   // This test method will be executed
   // during the installation of the package.
   @isTest(OnInstall=true)
   static void test1() {
      // Some test code
   }

   // Tests excluded from running during the
   // the installation of a package.
   @isTest
   static void test2() {
      // Some test code
   }

   static testmethod void test3() {
      // Some test code
   }
}
``` 
**[@IsTest(isParallel=true)](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_isTest.htm)**
---
**`【概要説明】`**
並列実行できるテストクラスを示します。

**`【使用箇所】`**
クラスorメソッド

**`【考慮事項】`**

- 同時テスト数のデフォルト制限は、これらのテストクラスに適用されません。
- このアノテーションにより、より多くのテストを並列実行できるため、テストクラスをより効率的に実行できます。
- このアノテーションは、並列テストを無効にする設定を上書きします。
- @isTest(SeeAllData=true)アノテーションと@isTest(isParallel=true)アノテーションは、同じApexテストメソッドで同時に使用することはできません。

```java:使用例
@isTest(isParallel=true)
public with sharing class UnitTest {
　　//Test class
}
``` 
**[@ReadOnly](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_ReadOnly.htm)**
---
**`【概要説明】`**
Visualforceから要求したクエリが最大1,000,000行を取得できるようになる
また、繰り返し表示用のコンポーネント(<apex:dataTable>、<apex:dataList>、<apex:repeat>)が扱える項目数が1000→10000になる

**`【使用箇所】`**
メソッド

**`【考慮事項】`**

- staticであること
- global、またはpublicであること
- Webserviceとして定義すること、または@RemoteActionアノテーションを併せて付加すること
- このメソッド内で取得したレコードはUpdateしたり、非同期メソッドを呼び出す不可

```java:使用例
public with sharing class ReadOnlyController{
  @ReadOnly
  @RemoteAction
  public String getRecord() {
    //50,000件を超えるレコードを取得できる
    List<Lead> leads = [SELECT Id, Name FROM Lead];
    return 'ok';
  }
}
``` 
**[@RemoteAction](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_RemoteAction.htm)**
---
**`【概要説明】`**
JavaScriptからAPexメソッドを呼び出すことが可能です。

**`【使用箇所】`**
メソッド

**`【考慮事項】`**

- staticであること
- global、またはpublicであること
- JavaScript Remotingコールには、API制限は適用されませんが、JavaScript Remotingを使用する Visualforceページには、すべての標準Visualforceの制限が適用されます。

```java:使用例
public with sharing class RemoteActionController{
  @RemoteAction
  public static String getRecord(String strParam) {
    String response = 'xxxxxxxxxx';
    return response;
  }
}
``` 
**[@SuppressWarnings](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_SuppressWarnings.htm)**
---
**`【概要説明】`**
このアノテーションは Apex では何も行いませんが、
サードパーティツールに情報を提供するために使用できます。

**`【使用箇所】`**

**`【考慮事項】`**

```:使用例
``` 
**[@TestSetup](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_testsetup.htm)**
---
**`【概要説明】`**
テストメソッド前に一回のみ実行します。
作成されたテストデータは各メソッドからアクセスです。

**`【使用箇所】`**
メソッド

**`【考慮事項】`**
テストクラスごとに使用できるテスト設定メソッドは 1 つのみです。

```java:使用例
@isTest
private class XXXXXXTest {
	@testSetup
	static void setup() {
		Account acc = new Account(Name = 'Sample Account');
		insert acc;
	}

	@isTest
	static void test1() {
		// @testSetupで作成したレコードをSOQLで取得できる
    	Account acc = [SELECT Id, Name FROM Account];
    }
}

``` 
**[@TestVisible](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_testvisible.htm)**
---
**`【概要説明】`**
Privateまたはprotectedメンバーはテストクラスへ公開する

**`【使用箇所】`**
変数／メソッド／内部クラス

**`【考慮事項】`**
この TestVisible アノテーションは、テストコードと非テストコードが混在する既存のクラスの Salesforce API バージョンをアップグレードする場合にも便利です。**API バージョン 28.0 以降ではテストメソッドが非テストクラスで使用できなくなる**ため、クラスの API バージョンをアップグレードする場合に、古いクラスから新しいクラス (isTest アノテーションが付加されたクラス) にテストメソッドを移動する必要があります。元のクラスの非公開メソッドまたはメンバー変数にアクセスするときに、表示に関する問題が生じる場合があります。この場合は、これらの非公開メンバーに TestVisible アノテーションを付加します。

```java:使用例
public class VisibleSampleClass {
    // Private member variables
    @TestVisible private Integer recordNumber = 0;
    @TestVisible private String areaCode = '(415)';
    // Public member variable
    public Integer maxRecords = 1000;
    
    // Private inner class
    @TestVisible class Employee {
        String fullName;
        String phone;
        
        // Constructor
        @TestVisible Employee(String s, String ph) {
            fullName = s;
            phone = ph;
        }
    }
       
    // Private method
    @TestVisible private String privateMethod(Employee e) {
        System.debug('I am private.');
        recordNumber++;
        String phone = areaCode + ' ' + e.phone;
        String s = e.fullName + '\'s phone number is ' + phone;
        System.debug(s);
        return s;
    }
    
    // Public method
    public void publicMethod() {
        maxRecords++;
        System.debug('I am public.');    
    }
    
    // Private custom exception class
    @TestVisible private class MyException extends Exception {}
}
``` 
**[@RestResource(urlMapping=’/yourUrl’)](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_rest_resource.htm)**
---
**`【概要説明】`**
Apex クラスを REST リソースとして公開する

**`【使用箇所】`**
Apex クラス

**`【考慮事項】`**

- URL 対応付けは、https://instance.salesforce.com/services/apexrest/ と相対的です。
- ワイルドカード文字 (*) を使用することができます。
- **URL の対応付けでは、大文字と小文字は区別されます。**
- このアノテーションを使用するには、Apex クラスがグローバルとして定義されている必要があります。


HTTPメソッドによって、下記アノテーションのメソッドを用意する必要があります。
　**[@HttpGet](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_http_get.htm)：Read
　[@HttpPost](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_http_post.htm)：Create
　[@HttpPatch](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_http_patch.htm)：Update
　[@HttpPut](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_http_put.htm)：Upsert
　[@HttpDelete](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_http_delete.htm)：Delete**

```java:使用例
@RestResource(urlMapping='/XXXXXX/*')
global with sharing class XXXXXXRestAPI {
	@HttpGet
	global static ResponseWrapper doGet() {
		ResponseWrapper response = new ResponseWrapper();
		try {
			// 業務処理
			// ～～省略～～

			// 正常終了
			response.isSuccess = true;
		} catch(Exception e){
			// 異常終了
			response.isSuccess = false;
			response.message = 'システムエラーが発生しました。' + e.getMessage();
		}
		
		return response;
	}
	
	@HttpPost
	global static ResponseWrapper doPost(RequestWrapper request) {
		ResponseWrapper response = new ResponseWrapper();
		try {
			// 業務処理
			// ～～省略～～

			// 正常終了
			response.isSuccess = true;
		} catch(Exception e){
			// 異常終了
			response.isSuccess = false;
			response.message = 'システムエラーが発生しました。' + e.getMessage();
		}
		
		return response;
	}
	
	global class RequestWrapper {
		Account acct;
	}
	
	global class ResponseWrapper {
		Boolean isSuccess;
		String message;
		
		Account acct;
		List<Contact> contList;
	}
}
```