User Tools

Site Tools


salesforce_helpful_tips

Helpful Tips

Here you will find some tips and tricks to help in using the Perspectium Replicator application in your Salesforce org. For any questions, please contact support@perspectium.com

401 Session Expired or Invalid

When saving properties, if you receive the error Status Code[401] Body: [{“message”:“Session expired or invalid”,“errorCode”:“INVALID_SESSION_ID”}], try generating a new security token especially if you have change the password of the account you're using for the dynamic share trigger. You may also want to verify the consumer key you are using has not changed as well.

Salesforce Errors Subscribing to Records from ServiceNow

  • Check that the dynamic or bulk share configuration in ServiceNow for sharing out records uses “AES128” as the cipher
  • Check the [snc_table_maps|table map]] used specifies “JSON” as the format

The value provided for foreign key reference <field_name> is not a nested SObject

For cases where you are replicating a record to Salesforce and your record includes a reference field to another table, you may get the above error related to the field. For example, if you have a Case record and are referencing the Account field where your JSON looks like this:

{"Subject":"Test""Id":"00000000000001","Description":"Test","attributes":{"type":"Case"},
"Account":"20000000000002"}

You may get this error:

The value provided for foreign key reference Account is not a nested SObject

In this case, because your reference field (Account) is referencing another table and you're passing the Id value of a record in that table, you will want to use the field name with “Id” appended to the end i.e. “AccountId”:

{"Subject":"Test","Id":"00000000000001","Description":"Test","attributes":{"type":"Case"},
"AccountId":"20000000000002"}

Custom Fields

For custom fields defined as a lookup (reference) field to another table:

You set the Id value to the API Name of the field and will need to use the 18 character (and not the 15 character) Id value. For example:

 
{"Id":"00000000000001", "attributes":{"type":"Case"}, "persp__CaseContact__c":"0031a00000EUHLMAA5"}

Cannot deserialize instance of datetime from VALUE_STRING (JSON_PARSER_ERROR)

Datetime fields require datetimes be set in the IS0 8601 format. Depending on the formatter set with your datetime field (check with your Salesforce administrator), this would be in the format “2007-04-05T14:30:12.000Z” or “2007-04-05T12:30:12-02:00”.

For example:

"SystemModstamp":"2017-12-08T06:41:13.000Z"
"Arrival":"2017-12-08T00:41-0600"

SObject type does not allow triggers

When creating a new dynamic share and selecting “Save Trigger”, you may get the following error:

Failed to create Dynamic Share trigger [PSP_test_CaseHistoryTrigger]: Status Code[400] Body: [{"message":"SObject type does not allow triggers: CaseHistory","errorCode":"INVALID_FIELD_FOR_INSERT_UPDATE","fields":[]}]

Because Salesforce doesn't allow you to create triggers on every table (sobject), this error will appear when trying to save and create the trigger. For these tables, you will want to use the bulk share option instead.

In the B Release, the list of tables in the dynamic share form will only show tables that support Apex triggers.

CreatedById and LastModifiedById User

By default, records modified by the Salesforce application will show created by and last modified by the user who started the Perspectium Replicator Subscriber job.

In order to reflect the actual user by passing in ID values for the CreatedById and LastModifiedById fields, you will need to have Create Audit Fields enabled.

Per Salesforce, once enabled, you will be able to set these fields when creating new records. Since these fields are intended to be audit fields, you will only be able to set them on create, not update. If the records already exist in Salesforce, they will need to be exported to a .csv file, deleted in Salesforce, and then imported with the updated information as new records.

Coalescing on an External ID Field

By default, records subscribed into Salesforce will coalesce on the Id field to determine if we should insert a new record or update a current record. So in most cases, you will want to create JSON messages to be consumed into Salesforce with the record's Id as found in Salesforce.

For example, if you are replicating records between ServiceNow and Salesforce, you can use the table map feature of the Perspectium Replicator ServiceNow application to map out a field that holds the record's Salesforce Id. This Id field will generally be saved as the correlation_id field in ServiceNow tables. That way when the record is subscribed into Salesforce, it can use this Id field to find the record and update or insert as appropriate.

However there may be cases where you want records in Salesforce to coalesce on an External ID field (such as when you want Salesforce to coalesce on the replicated record's ServiceNow sys_id) since records may generally be created on another platform like ServiceNow versus starting in Salesforce. Another reason is you may prefer to have more control in the ServiceNow app and have it be your central location for all data transformation and thus want to control coalescing there as well.

To set this up, do the following:
1) Create a new custom field on the table in Salesforce where you want to coalesce on an External ID field. Select the field as a “Text” field and choose the “External ID” option:

2) In Perspectium messages sent to Salesforce, you will want to add “ExternalIDField” and “ExternalIDValue” attributes so that when the message is received in Salesforce, it knows what the name of the external ID field is and what value to query for:

Attribute Name Description
ExternalIDFieldThe name of the External ID field in Salesforce as created in step 1
ExternalIDValue A record's external ID value that we will use to query for in Salesforce in the External ID field

Using the above example, when the message is subscribed into Salesforce, the app will query the Case table and look for a record with ExternalID__c = 'f4e2e6104f120300b6a444b18110c726' and if it finds a record as such, use that record to update.

For ServiceNow to Salesforce, you will want to use the table map feature since it supports creating attributes in the outbound message. You can create a field map to target each of the above attributes:

In this example, the ExternalIdField is scripted to always use the same value since the custom External ID field in Salesforce will always be the same field name while the record's sys_id is used for the External ID field's value.

The Salesforce app will automatically query for the specified External ID field and value if both attributes exist; otherwise it will coalesce by the Id field with its normal default behavior.

2017/12/28 21:55 · Paul Nguyen

Subscribing to Case Comments

Since Salesforce stores comments in a separate table, when sharing out a Case's comments, you would share out the CaseComment table and then subscribe these records into an import set table that targets the sys_journal_field table.

However to get these comments to refresh properly in the incident's activity log as well as fire notifications, the best way to save these comments is using an onBefore transform map script in the import set table you create that targets the sys_journal_field table.

Based on the incoming CaseComment JSON containing a reference to the Case record as stored in the ParentId field (which is mapped to u_parentid when read into the import set table) and this Case record ID stored in the correlation_id field in the incident table in ServiceNow, this script will find the incident record to add the comment through the incident:

var incsysid='';
var inc = new GlideRecord('incident');
inc.addQuery('correlation_id',source.u_parentid);
inc.query();
if (inc.next()){
    incsysid = inc.sys_id;  //find sysid of incident from parentid in JSON
}

var gr = new GlideRecord('sys_journal_field');
gr.addQuery('name', 'incident');
gr.addQuery('element_id', incsysid);
gr.addQuery('value', source.u_commentbody);
gr.query();
if (gr.getRowCount() > 0) {
    ignore = true; // found comment already previously don't need to re-add
}
else {
    var igr = new GlideRecord('incident');
    if (igr.get(incsysid)) {
        igr.comments.setJournalEntry(source.u_commentbody);
        igr.update();
        ignore = true;
    }
}

Doing this will ensure the activity log refreshes properly and any notifications set for incident comments also fire.

salesforce_helpful_tips.txt · Last modified: 2018/01/15 22:17 by paul