No Results
Search Tips:
- Please consider misspellings
- Try different search keywords
Newer Version Available
future メソッド
future メソッドは、バッググラウンドで非同期で実行されます。外部 Web サービスへのコールアウト、独自のスレッドを独自の時間に実行する処理など、長時間にわたる処理を実行する場合に future メソッドをコールできます。また、混合 DML エラーを回避するために異なる sObject 型に対する DML 操作を分離する場合にも future メソッドを使用できます。各 future メソッドは、キューに入れられ、システムリソースが使用可能になったときに実行されます。この方法によって、長時間にわたる処理の完了を待たずにコードを実行できます。future メソッドを使用する利点は、SOQL クエリの制限やヒープサイズ制限など、一部のガバナ制限値が高くなる点にあります。
future メソッドを定義するには、単に次のように future アノテーションを使用してアノテーションを付加します。
1swfobject.registerObject("clippy.codeblock-0", "9");global class FutureClass
2{
3 @future
4 public static void myFutureMethod()
5 {
6 // Perform some operations
7 }
8}future アノテーションのあるメソッドは静的メソッドである必要があり、void 型のみを返します。指定するパラメータはプリミティブデータ型、プリミティブデータ型の配列、プリミティブデータ型のコレクションである必要があります。future アノテーションのあるメソッドは、sObject またはオブジェクトを引数として取ることはできません。
future メソッドに sObject を引数として渡せない理由は、メソッドをコールしてからそのメソッドを実行するまでの間に sObject が変更されてしまう可能性があるためです。この場合、future メソッドが以前の sObject 値を取得して新しい値を上書きしてしまう可能性があります。 データベースにすでに存在する sObject を使用するには、代わりに sObject ID (または ID のコレクション) を渡し、ID を使用して最新のレコードに対してクエリを実行します。次の例では、ID のリストを使用してこれを実行する方法を示します。
1swfobject.registerObject("clippy.codeblock-1", "9");global class FutureMethodRecordProcessing
2{
3 @future
4 public static void processRecords(List<ID> recordIds)
5 {
6 // Get those records based on the IDs
7 List<Account> accts = [SELECT Name FROM Account WHERE Id IN :recordIds];
8 // Process records
9 }
10}次の例は、外部サービスへのコールアウトを実行する future メソッドの骨格です。このアノテーションは、コールアウトが許可されることを示す追加パラメータ (callout=true) を取っています。コールアウトについての詳細は、「Apex を使用したコールアウトの呼び出し」を参照してください。
1swfobject.registerObject("clippy.codeblock-2", "9");global class FutureMethodExample
2{
3 @future(callout=true)
4 public static void getStockQuotes(String acctName)
5 {
6 // Perform a callout to an external service
7 }
8
9}null 以外のロールを持つユーザの挿入は、他の sObject に対する DML 操作とは別のスレッドで実行する必要があります。次の例では、future メソッドを使用してこれを行っています。future メソッド insertUserWithRole は、Util クラスで定義され、COO ロールを持つユーザの挿入を実行します。この future メソッドを使用するには、組織に COO ロールを定義しておく必要があります。MixedDMLFuture の useFutureMethod メソッドで、取引先が挿入され、future メソッド insertUserWithRole がコールされます。
次は、null 以外のロールを持つユーザを挿入する future メソッドが含まれる、Util クラスの定義です。
1swfobject.registerObject("clippy.codeblock-3", "9");public class Util {
2 @future
3 public static void insertUserWithRole(
4 String uname, String al, String em, String lname) {
5
6 Profile p = [SELECT Id FROM Profile WHERE Name='Standard User'];
7 UserRole r = [SELECT Id FROM UserRole WHERE Name='COO'];
8 // Create new user with a non-null user role ID
9 User u = new User(alias = al, email=em,
10 emailencodingkey='UTF-8', lastname=lname,
11 languagelocalekey='en_US',
12 localesidkey='en_US', profileid = p.Id, userroleid = r.Id,
13 timezonesidkey='America/Los_Angeles',
14 username=uname);
15 insert u;
16 }
17}これは、上記で定義した future メソッドをコールするメインメソッドが含まれるクラスです。
1swfobject.registerObject("clippy.codeblock-4", "9");public class MixedDMLFuture {
2 public static void useFutureMethod() {
3 // First DML operation
4 Account a = new Account(Name='Acme');
5 insert a;
6
7 // This next operation (insert a user with a role)
8 // can't be mixed with the previous insert unless
9 // it is within a future method.
10 // Call future method to insert a user with a role.
11 Util.insertUserWithRole(
12 'mruiz@awcomputing.com', 'mruiz',
13 'mruiz@awcomputing.com', 'Ruiz');
14 }
15}future メソッドを呼び出す方法は、他のメソッドを呼び出す方法と同じです。ただし、future メソッドで別の future メソッドを呼び出すことはできません。
future アノテーションのあるメソッドには次のような制限事項があります。
- Apex 呼び出しごとの、メソッドのコール数は 50 以下にする必要があります。
- 24 時間あたりの future メソッドの最大呼び出し数は、250,000 または組織のユーザライセンス数の 200 倍のいずれか大きいほうです。これは組織全体の制限で、他のすべての非同期 Apex (Apex 一括処理、キュー可能 Apex、スケジュール済み Apex、および future メソッド) と共有されます。この制限のカウント対象となるライセンスは、Salesforce フルユーザライセンスまたは Force.com アプリケーションサブスクリプションのユーザライセンスです。Chatter Free、Chatter カスタマーユーザ、カスタマーポータルユーザ、およびパートナーポータルユーザライセンスは含まれません。
future メソッドのテスト
future アノテーションのあるメソッドをテストするには、startTest()、stopTest() コードブロック内でメソッドを含むクラスをコールします。startTest メソッドの後に作成されたすべての非同期コールはシステムによって収集されます。stopTest を実行する場合、すべての非同期プロセスが同期して実行されます。
1swfobject.registerObject("clippy.codeblock-5", "9");@isTest
2private class MixedDMLFutureTest {
3 @isTest static void test1() {
4 User thisUser = [SELECT Id FROM User WHERE Id = :UserInfo.getUserId()];
5 // System.runAs() allows mixed DML operations in test context
6 System.runAs(thisUser) {
7 // startTest/stopTest block to run future method synchronously
8 Test.startTest();
9 MixedDMLFuture.useFutureMethod();
10 Test.stopTest();
11 }
12 // The future method will run after Test.stopTest();
13
14 // Verify account is inserted
15 Account[] accts = [SELECT Id from Account WHERE Name='Acme'];
16 System.assertEquals(1, accts.size());
17 // Verify user is inserted
18 User[] users = [SELECT Id from User where username='mruiz@awcomputing.com'];
19 System.assertEquals(1, users.size());
20 }
21}