Apex SDK
InCountry Apex SDK allows users of the InCountry Data Residency for Salesforce app to make CRUD (create/read/update/delete) operations with their regulated data stored in InCountry PoPs (Points of Presence). Apex SDK is provided as a part of the InCountry Data Residency for the Salesforce app. All the SDK components are defined as global Apex classes. That’s why the SDK can be used by the app subscribers within their custom code solutions.
Replication model
InCountry Apex SDK for the replication data regulation model supports the four basic operations:
Find
Write
Batch write
Delete
Internally, Apex SDK automatically differentiates records by country and makes callouts to InCountry Rest API.
InCountry Rest API endpoints must be registered within the InCountryRestAPIEndpoint
custom metadata type and added into the remote site settings to allow server-side callouts. This guide does not cover the initial setup and configuration of InCountry Data Residency for Salesforce. You can find all the relevant information about this at our documentation site.
Quick Start Guide
To access operations available in InCountry PoP, you need to create an instance of the InCountry
class. You should prepend the InCountry Managed Package namespace to the class name, like <namespace>.InCountry
. For example, if the namespace of the InCountry Data Residency for Salesforce package is testIncountry1
, you need to use the following class name: testIncountry1.InCountry
.
All the following code samples below are provided without a namespace. Please prepend the InCountry Namespace to class names.
How to instantiate Apex SDK
You need to execute the static getInstance()
method from the InCountry
class. It returns an instance of Apex SDK.
InCountry service = InCountry.getInstance();
How to find records stored in InCountry Platform
You can find records stored in the InCountry Platform by using two different approaches:
by records ids;
by records instances.
Apex SDK will automatically split records by country and make callouts to appropriate InCountry Points of Presence located in each target country. For example, if you want to fetch two leads stored in InCountry Sweden
and one account stored in InCountry Russia
, Apex SDK will make two callouts: one callout to Sweden and the other callout to Russia.
- Finding by records ids
In this scenario, you should provide a set of record ids. Please consider that Apex SDK will perform additional SOQL queries to retrieve records from the Salesforce database. For example, if you provide three account Ids and five lead Ids, the SDK will perform two additional SOQL queries to retrieve accounts and leads from the database. These SOQL queries are required because the SDK should fetch all the regulated field values and the record storing countries from the database. In the following example, the SDK will fetch two leads and one account from the InCountry Platform.
InCountry service = InCountry.getInstance();
Set<Id> input = new Set<Id>{'00Q5w00001vsLjVEAU', '00Q5w00001vrzjQEAQ', '0015w00002OUr9uAAD'};
List<InCountry.FindResult> results = service.find(input);
- Finding by record instances
If you have queried all the necessary records from the Salesforce database, you can provide the record instances to the find()
method so that the SDK will skip additional SOQL queries. Please ensure that all the required fields are included in your SOQL queries. Apex SDK requires all the regulated fields and the Source Country Field
field to use the record-level policy for determining the record originating country.
InCountry service = InCountry.getInstance();
List<Lead> input = [SELECT Id, FirstName, Email,
Phone, Country_Field__c
FROM Lead
ORDER BY CreatedDate DESC
LIMIT 10];
List<InCountry.FindResult> results = service.find(input);
The FindResult
class contains data returned from the InCountry Platform:
@JsonAccess(serializable='always' deserializable='always')
global class FindResult {
@AuraEnabled global List<RecordData> data;
@AuraEnabled global Map<String, String> meta;
}
The RecordData
class represents a single Salesforce record stored in InCountry Platform:
@JsonAccess(serializable='always' deserializable='always')
global class RecordData {
@AuraEnabled global String key;
@AuraEnabled global String record_key;
@AuraEnabled global String profile_key;
@AuraEnabled global String range_key;
@AuraEnabled global String body;
@AuraEnabled global String key1;
@AuraEnabled global String key2;
@AuraEnabled global String key3;
@AuraEnabled global String key4;
@AuraEnabled global String key5;
@AuraEnabled global String key6;
@AuraEnabled global String key7;
@AuraEnabled global String key8;
@AuraEnabled global String key9;
@AuraEnabled global String key10;
@AuraEnabled global String key11;
@AuraEnabled global String key12;
@AuraEnabled global String key13;
@AuraEnabled global String key14;
@AuraEnabled global String key15;
@AuraEnabled global String key16;
@AuraEnabled global String key17;
@AuraEnabled global String key18;
@AuraEnabled global String key19;
@AuraEnabled global String key20;
@AuraEnabled global String created_at;
@AuraEnabled global String updated_at;
@AuraEnabled global List<FileData> attachments;
}
The FileData
class represents a single file linked to a specific InCountry record:
@JsonAccess(serializable='always' deserializable='always')
global class FileData {
@AuraEnabled global String file_id;
@AuraEnabled global String filename;
@AuraEnabled global String hash;
@AuraEnabled global String mime_type;
@AuraEnabled global Integer size;
@AuraEnabled global String created_at;
@AuraEnabled global String updated_at;
@AuraEnabled global String download_link;
@AuraEnabled global String error;
}
How to write records into InCountry Platform
Like the find
operation, you can use two different methods to write single Salesforce records into the InCountry Platform.
- Writing by record ids
Please consider that Apex SDK will perform an additional SOQL query to fetch a salesforce database record. If the current user on behalf of whom an operation is executed has no sufficient permissions to the record id, an exception will be thrown.
InCountry service = InCountry.getInstance();
InCountry.WriteRequest result = service.write('00Q5w00001vrzjQEAQ');
- Writing by record instance
Before executing the write(SObject record)
method, ensure that you have included all the necessary regulated and country fields into your SOQL queries.
InCountry service = InCountry.getInstance();
Lead input = [SELECT Id, FirstName, Email, Phone, Country_Field__c
FROM Lead
LIMIT 1];
input.FirstName = 'ChangedValue';
InCountry.WriteRequest result = service.write(input);
The WriteRequest
class represents a confirmation from the InCountry Platform.
@JsonAccess(serializable='always' deserializable='always')
global class WriteRequest {
@AuraEnabled global String country;
@AuraEnabled global String profile_key;
@AuraEnabled global String body;
@AuraEnabled global String record_key;
@AuraEnabled global String key;
@AuraEnabled global String key1;
@AuraEnabled global String key2;
@AuraEnabled global String key3;
@AuraEnabled global String key4;
@AuraEnabled global String key5;
@AuraEnabled global String key6;
@AuraEnabled global String key7;
@AuraEnabled global String key8;
@AuraEnabled global String key9;
@AuraEnabled global String key10;
@AuraEnabled global String key11;
@AuraEnabled global String key12;
@AuraEnabled global String key13;
@AuraEnabled global String key14;
@AuraEnabled global String key15;
@AuraEnabled global String key16;
@AuraEnabled global String key17;
@AuraEnabled global String key18;
@AuraEnabled global String key19;
@AuraEnabled global String key20;
}
How to write multiple records into InCountry Platform
Apex SDK performs requests to a separate /api/records/batch
endpoint in InCountry Rest API to write multiple records to InCountry Platform to perform batch write operations. Apex SDK will automatically split records by country and will make several callouts to different InCountry Points of Presence in the target countries. For example, if you want to write two Leads to InCountry Sweden
and one account to InCountry Russia
, Apex SDK will make two callouts, as follows: one callout to Sweden and the other callout to Russia.
- Writing a batch of records by records ids
Please consider that InCountry SDK will perform additional SOQL queries to fetch records from the Salesforce database. If the current user on behalf of whom an operation is executed has no sufficient permissions to record id, an exception will be thrown.
For example, if you provide three account ids and five lead ids, the SDK will perform two additional SOQL queries to fetch accounts and leads from the database. These SOQL queries are required because Apex SDK should take all the regulated field values and record originating countries from the database.
InCountry service = InCountry.getInstance();
Set<Id> input = new Set<Id>{'00Q5w00001vsLjVEAU', '00Q5w00001vrzjQEAQ', '0015w00002OUr9uAAD'};
List<InCountry.WriteRequest> result = service.write(input);
- Writing a batch of records by record instances
Before executing the write(List<SObject> records)
method, ensure that you have all the required regulated and country fields included in your SOQL queries.
InCountry service = InCountry.getInstance();
List<Lead> input = [SELECT Id, FirstName, Email, Phone, Country_Field__c
FROM Lead
LIMIT 40];
for (Lead leadRecord : input) {
leadRecord.Phone = '+37529000000';
}
List<InCountry.WriteRequest> result = service.write(input);
How to remove records from InCountry Platform
As of now, the InCountry Platform does not support batch delete operations. If you want to delete multiple records from the InCountry Platform, please consider that Apex SDK will perform multiple callouts.
- Removing a single record by record id
Please consider that Apex SDK will perform an additional SOQL query to fetch a record from the Salesforce database.
InCountry service = InCountry.getInstance();
Id input = '0015w00002OUr9uAAD';
InCountry.DeleteResult result = service.remove(input);
- Removing multiple records by records ids
Please consider that Apex SDK will perform additional SOQL queries to fetch your records from the Salesforce database. In the following example, Apex SDK will perform two additional SOQL queries and three callouts.
InCountry service = InCountry.getInstance();
Set<Id> input = new Set<Id>{'00Q5w00001vsLjVEAU', '00Q5w00001vrzjQEAQ', '0015w00002OUr9uAAD'};
List<InCountry.DeleteResult> result = service.remove(input);
Error handling
The SDK may throw the following exception:
SObject was retrieved without a required field. For example, you need to specify the Source Country field if you are using a record-level policy set for a current SObject.