' P '

whatever I will forget

Apex Webサービス

概要

  • Apex クラスメソッドを REST または SOAP Web サービス処理として公開可能
    • メソッドを Web 経由でコールできるようにすることで、外部アプリケーションと Salesforce を統合可能

#ApexクラスをREST Webサービスとして使用する - クラスの定義、メソッドはGlobalにする(メソッドはstaticにしておく)
- アノテーション (@hoge) を下記のように定義する
- getRecord()メソッドはカスタムREST APIコール。GET要求で呼び出される。

@RestResource(urlMapping='/Account/*')
global with sharing class MyRestResource {
    @HttpGet
    global static Account getRecord() {
        // Add your code
    }
}
  • @RestResourceについて
    • Apex RESTのベースエンドポイントは https://yourInstance.my.salesforce.com/services/apexrest/
    • 上記例だと https://yourInstance.my.salesforce.com/services/apexrest/Account/*となる
アノテーション アクション 詳細
@HttpGet 参照 レコードを参照または取得します。
@HttpPost 作成 レコードを作成します。
@HttpDelete 削除 レコードを削除します。
@HttpPut 更新/挿入 通常、既存のレコードを更新したり、レコードを作成したりするために使用します。
@HttpPatch 更新 通常、既存のレコードの項目を更新するために使用します。

ApexクラスをSOAP Webサービスとして使用する

  • RESTとほぼ同じだが、メソッドにwebserviceキーワードを追加する
    • 上記メソッドはGlobal扱いになる
global with sharing class MySOAPWebService {
    webservice static Account getRecord(String id) {
        // Add your code
    }
}

Session IDの取得

  • REST エンドポイントを「cURL」するたびに、認証用のセッション ID が渡される
  • 設定方法は下記
    developer.salesforce.com

  • 下記を実行し、成功した場合の access_tokenSession ID

curl -v https://login.salesforce.com/services/oauth2/token -d "grant_type=password" -d "client_id=<your_consumer_key>" -d "client_secret=<your_consumer_secret>" -d "username=<your_username>" -d "password=<your_password_and_security_token>" -H "X-PrettyPrint:1"
  • 下記を実行するとレコードが返される。
  • Trailheadの構文のままやると zsh: event not found となったので下記で実施
curl https://yourInstance.my.salesforce.com/services/apexrest/Cases/<Record_ID> -H 'Authorization: Bearer <your_session_id>' -H "X-PrettyPrint:1"

salesforce.stackexchange.com

PATCHメソッド

レコードの項目を更新する際に使用するらしい
やり方は2つ。
1. メソッドでパラメータを指定して各項目を更新(更新したい項目ごとにメソッドを定義する必要がある)
2. リクエストボディでJSONの名前/値のペアで渡す (こちらの方が柔軟性は高い)

例のソースは方法2.

    @HttpPatch
    global static ID updateCaseFields() {
        RestRequest request = RestContext.request;
        String caseId = request.requestURI.substring(
            request.requestURI.lastIndexOf('/')+1);
        Case thisCase = [SELECT Id FROM Case WHERE Id = :caseId];
        // Deserialize the JSON string into name-value pairs
        Map<String, Object> params = (Map<String, Object>)JSON.deserializeUntyped(request.requestbody.tostring());
        // Iterate through each parameter field and value
        for(String fieldName : params.keySet()) {
            // Set the field and value on the Case sObject
            thisCase.put(fieldName, params.get(fieldName));
        }
        update thisCase;
        return thisCase.Id;
    }  

Apex RESTクラスのテスト

  • テストメソッドでRestRequestを作成し、要求のプロパティを設定する
// Set up a test request
RestRequest request = new RestRequest();
// Set request properties
request.requestUri =
    'https://yourInstance.my.salesforce.com/services/apexrest/Cases/'
    + recordId;
request.httpMethod = 'GET';
// Set other properties, such as parameters
request.params.put('status', 'Working');
// more awesome code here....
// Finally, assign the request to RestContext if used
RestContext.request = request;

Challenge

なんでか知らんがこのコードならPass.
urlMappingはこうじゃないとダメっぽい.
@RestResource(urlMapping='/Accounts/*/contacts')

NG: @RestResource(urlMapping='/Accounts/*/Contacts')

@RestResource(urlMapping='/Accounts/*/contacts')
global with sharing class AccountManager {
    @HttpGet
    global static Account getAccount() {
        RestRequest request = RestContext.request;
        system.debug(request.requestURI);
        // grab the caseId from the end of the URL
        String accountId = request.requestURI.substringBetween('/Accounts/', '/contacts');
        Account result =  [SELECT Id, Name, (SELECT Id, Name FROM Contacts)
                        FROM Account
                        WHERE Id = :accountId];
        return result;
    }
}
@IsTest
private class AccountManagerTest {
    @isTest static void testgetAccount() {
        Id accountRecordId = createTestAccountRecord();
        // Set up a test request
        RestRequest request = new RestRequest();
        request.requestUri = 'https://yourinstance.my.salesforce.com/services/apexrest/Accounts/' + accountRecordId + '/contacts';
        request.httpMethod = 'GET';
        RestContext.request = request;
        // Call the method to test
        Account thisAccount = AccountManager.getAccount();
        // Verify results
        System.assert(thisAccount != null);
        System.assertEquals('Test record', thisAccount.Name);
    }
    // Helper method
    static Id createTestAccountRecord() {
        // Create test record
        Account accountTest = new Account(Name='Test record');
        insert accountTest;
        Contact contactTest = new Contact(AccountId=accountTest.Id, FirstName='TestFirstName', LastName='TestLastName');
        insert contactTest;
        return accountTest.Id;
    }
}