Clean Suite for CRM: Salesforce Other#

Custom Code#

Use Clean Suite global Apex classes when you add package services to custom Salesforce automation.

Before You Write Code#

  1. Confirm the installed package namespace is MDPERSONATOR.

  2. Confirm the user has the required Clean Suite permission set.

  3. Confirm the target fields and Custom Mapping exist.

  4. Test the code in a sandbox.

  5. Check result codes and logs after each test.

Select an Execution Path#

Use this path to select the service execution method.

../../_images/CleanSuite_Other_SelectExecutionPath.png

Diagram flow

  1. Choose the execution method → Process one record

  2. Choose the execution method → Process a record set

  3. Choose the execution method → Run in a trigger with uncommitted work

  4. Process one record → Call the public Apex service method

  5. Process a record set → Start a batch job

  6. Run in a trigger with uncommitted work → Use a future method or asynchronous process

  7. Call the public Apex service method → Check result codes and logs

  8. Start a batch job → Check result codes and logs

  9. Use a future method or asynchronous process → Check result codes and logs

Call a Single-Record Service#

Use the service method that matches the data type.

Id recordId = '003000000000001AAA';
String addressResult = MDPERSONATOR.MD_GlobalAddressWSExt.doGlobalAddress(recordId);
String emailResult = MDPERSONATOR.MD_GlobalEmailWSExt.doGlobalEmail(recordId);
String phoneResult = MDPERSONATOR.MD_GlobalPhoneWSExt.doGlobalPhone(recordId);
String personResult = MDPERSONATOR.MD_PersonatorWSExt.doPersonator(recordId);

Use Trigger-Safe Callouts#

Do not call an HTTP service directly from a transaction that has uncommitted work. Use a package future method instead.

The package supplies these global future methods. Each method starts an asynchronous callout for one record.

Service

Future method

Global Address

MD_GlobalAddressWSExt.doOneGlobalAddress(Id recordId)

Global Email

MD_GlobalEmailWSExt.doOneGlobalEmail(Id recordId)

Global Phone

MD_GlobalPhoneWSExt.doOneGlobalPhone(Id recordId)

Personator

MD_PersonatorWSExt.doOnePersonator(Id recordId)

Property

MD_PropertyV4WSExt.doOneLookupProperty(Id recordId)

BusinessCoder

MD_BusinessWSExt.doOneBusinessCoder(Id recordId)

Each method carries the @Future(callout=true) annotation. It returns no value.

For a bulk trigger, use MD_PersonatorWSExt.doOnePersonatorBatch(List<Id> recordIDs). One call processes every record in the trigger.

Do not make one callout per record inside a trigger loop. Use a batch job for record sets.

Add a Trigger#

Call a future method from a trigger to avoid synchronous HTTP callouts in an uncommitted transaction.

This example shows a Contact trigger that verifies every new or updated Contact record with Personator.

// Trigger on Contact
trigger ContactPersonatorTrigger on Contact (after insert, after update) {
   Set<Id> contactIds = new Set<Id>();
   for (Contact c : Trigger.new) {
      contactIds.add(c.Id);
   }

   ContactPersonatorHandler.verifyContacts(new List<Id>(contactIds));
}

// Handler class
public class ContactPersonatorHandler {
   public static void verifyContacts(List<Id> contactIds) {
      if (contactIds.isEmpty()) {
            return;
      }

      MDPERSONATOR.MD_PersonatorWSExt.doOnePersonatorBatch(contactIds);
   }
}

Object: Contact

Why async is required: Triggers execute in a transaction with uncommitted work. HTTP callouts are forbidden in this state. The @Future(callout=true) method executes asynchronously after the transaction commits.

The package method MD_PersonatorWSExt.doOnePersonatorBatch is the asynchronous handler. The custom handler class above is synchronous and delegates to that package method.

Start a Batch Job#

Construct a package batch class, then pass it to `Database.executeBatch`. The batch constructors are global. Custom Apex can call them.

Id jobId = Database.executeBatch(
   new MDPERSONATOR.MD_PersonatorBatch(
      'SELECT Id FROM Contact LIMIT 10', // tested SOQL query
      true,                              // update the source record
      true,                              // process all records
      true,                              // use Clean Suite mappings
      'Mailing Address Verification'     // Custom Mapping name
   ),
   100                                    // Salesforce batch size
);

The package supplies four Clean Suite batch classes. Each class takes the same five constructor arguments.

Service

Batch class

Personator

MDPERSONATOR.MD_PersonatorBatch

Global Address

MDPERSONATOR.MD_GlobalBatch

Global Email

MDPERSONATOR.MD_GlobalEmailBatch

Global Phone

MDPERSONATOR.MD_GlobalPhoneBatch

The Custom Mapping must exist for the object and the service. If the mapping is absent, the job fails.

MD_CleanSuiteBatchController.executeBatchJob is package-internal. That method is public, not global. It drives the Clean Suite Batch Processing tab only. Custom Apex cannot call it.

Check the returned Async Apex job Id. Use Async Apex Jobs and Clean Suite Log to monitor the result.

Start a Batch Job from Anonymous Apex#

  1. Create the Custom Mapping for the object and service.

    ../../_images/Salesforce_CSBatch_01_ContactMapping.png

    The example uses a Contact mapping named Mailing Address Verification.

  2. Run the batch class from Developer Console > Execute Anonymous. Pass the mapping name.

    ../../_images/Salesforce_CSBatch_02_ExecuteCode.png

    Database.executeBatch returns the Async Apex job Id.

  3. Open Setup > Apex Jobs to review the job and its status.

    ../../_images/Salesforce_CSBatch_03_SeeResults.png

    The list shows the status, processed batches, and failure count.

Express Entry Lightning Action Override#

Use a custom Lightning Component to override the standard New action with an Express Entry form.

The packaged LX_ExpressEntry component cannot serve as an action override. It does not implement the lightning:actionOverride interface that Salesforce requires for a standard action.

Melissa supplies the sample code for the custom component. Download the archive before you start.

  1. Extract the archive. Confirm that it holds the three source files.

    The archive holds ExpressEntryNew.cmp, ExpressEntryNewController.js, and ExpressEntryNewHelper.js. Each file supplies one part of the new Lightning Component bundle.

  2. In Developer Console, create a Lightning Component bundle. Enter a descriptive name.

    ../../_images/SF-ExpressEntry_01_NewLightningBundle.png

    The example uses the name MD_ExpressEntry_Override.

  3. Copy the contents of ExpressEntryNew.cmp into the .cmp file of the new bundle. Save the file.

    ../../_images/SF-ExpressEntry_02_CopyPasteComponent.png

    Overwrite the generated markup. Press Ctrl+S to save the file.

  4. Copy the contents of ExpressEntryNewController.js into the controller .js file. Save the file.

    ../../_images/SF-ExpressEntry_03_CopyPasteController.png

    The controller handles the component events.

  5. Copy the contents of ExpressEntryNewHelper.js into the helper .js file. Save the file.

    ../../_images/SF-ExpressEntry_04_CopyPasteHelper.png

    The helper creates the record from the selected address.

  6. In Object Manager, open Buttons, Links, and Actions. Find the New action and click Edit.

    ../../_images/SF-ExpressEntry_05_EditAction.png

    Use the dropdown at the right of the action row.

  7. In Lightning Experience Override, select Lightning Component. Select the new component, then click Save.

    ../../_images/SF-ExpressEntry_06_SaveOverride.png

    The standard New action now opens the custom component.

  8. Open the object and select New. Select an address, then confirm that the record is created.

    ../../_images/SF-ExpressEntry_07_CreateNewRecord.png

    Click Create New to save the record with the selected address.

Test the override in a sandbox before you deploy it. An override replaces the standard action for every user of that object.

Error Handling#

Handle empty results and exceptions. Preserve the result codes and error details that help an administrator correct the mapping, license, or field permissions.

Training and Support#

Use these official Melissa resources for current product documentation and support.

Product Documentation#

Support#