Custom Merge Service
Learn how the SFDC connector enables you to use Custom Merge Service to implement the merge functionality.
The Custom Merge Service calls the Standard Merge Service for merging multiple objects. It is not mandatory to call the Standard Merge service for merging objects. Merging objects can be completed using the custom code. You can call a Standard Merge Service using the Custom Merge Service code.
Request
POST /customMergeService
Body
{
"type": {Salesforce object type} // e.g. Account
"ids": [] // list of ID's to merge
}
Response
HTTP CODE 200
The following table describes parameters required for the merge operation.
Parameter |
Type |
Required |
Description |
---|---|---|---|
success |
Boolean | true | Defines the status of the merge operation. The Possible values are true or false. |
winnerId |
String | true | Defines the sobject ID for the winners. |
loserIds |
Array of Strings | true | Defines the list of loser IDs. |
message |
String | false | Defines the error messages. |
{
"success": true/false;
"winnerId": {winnerId} // winner sobject id
"loserIds": [] // list of loser ids,
"message": "Error message"
}
Profile Configuration
You need to add customMergeService parameter to profile configuration to switch to Custom Merge Service.
{
"reltio": {
...
},
"salesforce": {
...
"customMergeService": "/customMergeService" // path to custom merge service.
}
}
Mapping configuration
Example for Mapping
[
{
"isActive": true,
"processMerge": true,
"customMerge": true,
"sfdcSource": "configuration/sources/SFDC",
"sobject": {
"type": "Account"
},
"reltioObjectType": "configuration/entityTypes/HCP",
"to_salesforce": {
...
},
"to_reltio": {
...
}
}
]
Example for Custom Merge Service
@RestResource(urlMapping='/customMergeService')
global with sharing class ReltioCustomMergeService {
global class HealthcheckResult {
String status = 'OK';
}
global class ReltioCustomMergeServiceResult {
boolean success { get; set; }
String winnerId;
List<String> loserIds;
String message { get; set; }
}
public class MergeException extends Exception {
}
@HttpGet
global static HealthcheckResult doGet() {
return new HealthcheckResult();
}
@HttpPost
global static ReltioCustomMergeServiceResult doPost(String type, List<String> ids){
ReltioCustomMergeServiceResult result = new ReltioCustomMergeServiceResult();
if (type == 'Account' || type == 'Contact') {
try {
// ids array is sorted alphabetically. The last item has the highest value
// Winner id has lowest value
String winnerId = ids[0];
List<String> loserIds = new List<String>();
for (Integer i = 1; i < ids.size(); i++) {
loserIds.add(ids[i]);
}
System.debug('Winner ID: ' + winnerId);
System.debug('Loser IDs: ' + loserIds);
// Merge in this example will be done by calling standard merge service
// Standard merge service allows to merge up to 3 objects at one time (one winner and up to 2 losers)
// If total objects count greater than three, then need to split losers to chunks.
List<String> chunk = new List<String>();
for (Integer i = 0; i < loserIds.size(); i++) {
chunk.add(loserIds[i]); // Split loser ids to chunks. Each chunk has up to 2 objects
if (chunk.size() == 2 || i == loserIds.size()-1) {
System.debug('Merge winner and chunk of losers: ' + chunk);
doMerge(type, winnerId, chunk); // call standard merge service for each chunk
chunk.clear();
}
}
result.success = true;
result.winnerId = winnerId;
result.loserIds = loserIds;
} catch (Exception e) {
System.debug('Unexpected exception: ' + e);
result.message = e.getMessage();
result.success = false;
}
} else {
System.debug('Type' + type + 'is not supported');
result.success = false;
result.message = 'Type' + type + 'is not supported';
return result;
}
return result;
}
public static void doMerge(String type, String winnerId, List<String> loserIds) {
if (type == 'Account' || type == 'Contact') {
System.debug('Execute standard merge for type: ' + type + ' Winner ID: ' + winnerId + ' Loser IDs: ' + loserIds);
mergeStandardObject(type, winnerId, loserIds);
} else {
System.debug('Type' + type + 'is not supported');
throw new MergeException('Custom merge for type' + type + ' is not supported');
}
}
private static void mergeStandardObject(String type, String winnerId, List<String> loserIds) {
sObject winner = getWinner(type, winnerId);
String query = 'Select Id from ' + type + ' where id in :loserIds';
System.debug('Get losers query: ' + query);
List<sObject> objectsToMerge = (List<sObject>)Database.query(query);
for (sObject objectToMerge: objectsToMerge) {
if (type == 'Account') {
merge ((Account) winner) (Account) objectToMerge;
} else if (type == 'Contact') {
merge ((Contact) winner) (Contact) objectToMerge;
}
System.debug('Successfuly merged ' + type + '(' + winnerId + ', ' + objectToMerge.Id + ')');
}
}
private static sObject getWinner(String type, String winnerId) {
String query = 'select Id from ' + type + ' where Id = :winnerId';
System.debug('Get winner query: ' + query);
List<sObject> winners = Database.query(query);
if (winners.size() == 0) {
throw new MergeException(type + ' for id ' + winnerId + ' is not found');
}
return winners[0];
}
}
Merging of Multiple Objects
The Custom Merge Service enables to override the Standard Merge Service logic. It is not mandatory to call the Standard Merge Service to perform the objects merge, it can be completely done using the custom code.
The Custom Merge Service allows calling Standard Merge Service from the code to perform the object merge.
Retry Logic for Merge Request
The connector can retry the merge requests based on the service response for the Custom Merge Service.
The requests would be retried repeatedly when the response contains"success":
false
. You can configure the retry count using salesforce.numRetries parameter in the relevant profile. For more information, see Configure your Salesforce Connector Profile.
"success": false
to
avoid data inconsistency. You can’t retry the requests if the Custom Merge Service provides an incorrect response structure (the structure without the winner or loser ID).