LET'S LEARN TOGETHER. THE BEAUTIFUL THING ABOUT LEARNING IS NOBODY CAN TAKE IT AWAY FROM YOU.

Using Apex with Knowledge

 


In continuation of my effort to make Lightning Knowledge easily understandable for all, today I am going to show how Salesforce Knowledge can be accessed using Apex. Salesforce Knowledge can have Apex Triggers and be accessible through Apex code. Actually, Salesforce provides some standard apex classes related to Knowledge Management that can be called for actions like publishing, editing as draft, archiving, and more.

Before I start, I would recommend you going through my earlier posts -

We can use the methods in KbManagement.PublishingService class to manage the lifecycle of an article. I am going to explain some of the few classes which developer needs mostly, but to know about all the methods, I highly recommend you going through the documentation here.

Editing an Article as Draft

We can use the below method to edit an article as draft - 

String newId = KbManagement.PublishingService.editOnlineArticle(
                    knowledgeArticleId,
                    false
               );

Where the 1st input parameter is the KnowledgeArticleId (Note - This is not the Knowledge Record Id).
2nd parameter is a Boolean value where false will not unpublish the already published articles and true will unpublish the already published article.

This method will return the new draft master version ID of the article.

Note - We need to keep this in mind that this method is not bulkified. So if you are trying to bulk edit a lot of published articles, this method will fail as it will throw Salesforce Limit. So the workaround is to implement Queueable class like below, where you call the queueable method with the batch size of your choice.

Queueable Class -

public class KnowledgeEditQueue implements Queueable {
List<Knowledge__kav> allKnowledges = new List<Knowledge__kav>();

public KnowledgeEditQueue(
List<Knowledge__kav> allKnowledges
) {
this. allKnowledges = allKnowledges;
}

public void execute(QueueableContext qc) {
List<String> newVersionIds = new List<String>();
String newVersionId;

for (Knowledge__kav single : allKnowledges) {
newVersionId = KbManagement.PublishingService.editOnlineArticle(
single.KnowledgeArticleId,
false
);
newVersionIds.add(newVersionId);
}
}

}

Calling the Queueable Method -
if (allArticles.size() > 0) {
    Integer count = 0;
List<Knowledge__kav> scope = new List<Knowledge__kav>();

for (Knowledge__kav single : allArticles) {
    if (count < BATCH_SIZE) {
    count++;
scope.add(single);
} else if (count == BATCH_SIZE) {
count = 0;
System.enqueueJob(new KnowledgeEditQueue(scope));
scope = new List<Knowledge__kav>();
scope.add(single);
}
}
if (!scope.isEmpty()) {
    System.enqueueJob(new KnowledgeEditQueue(scope));
}
}

Publish an Article 

We can use the below method to publish an article  - 

KbManagement.PublishingService.publishArticle(
      knowledgeArticleId,
      false
);

Where the 1st input parameter is the KnowledgeArticleId (Note - This is not the Knowledge Record Id).
2nd parameter is a Boolean value where false will not publish the article as a new version, whereas true will publish the article as a new version.

This method is not bulkified, so you can use the same mechanism of Queueable class to bulk publish articles.

Schedule Article Publication

We can use the below method to schedule article publication - 

Datetime scheduledDate = Datetime.newInstanceGmt(2012, 12,1,13,30,0);
KbManagement.PublishingService.scheduleForPublication(
      knowledgeArticleId,
      scheduledDate
);

Where the 1st input parameter is the KnowledgeArticleId (Note - This is not the Knowledge Record Id).
2nd parameter is the schedule date (If nothing is specified, then the article will be published immediately).


Delete Draft Article 

We can use the below method to delete draft article - 

KbManagement.PublishingService.deleteDraftArticle(
      knowledgeArticleId
);

Where the 1st input parameter is the KnowledgeArticleId (Note - This is not the Knowledge Record Id).

Archive Online Article

We can use the below method to archive online article - 

Datetime scheduledDate = Datetime.newInstanceGmt(2012, 12,1,13,30,0);
KbManagement.PublishingService.archiveOnlineArticle(
      knowledgeArticleId,
      scheduledDate
);

Where the 1st input parameter is the KnowledgeArticleId (Note - This is not the Knowledge Record Id).
2nd parameter is the schedule date (If nothing is specified, then the article will be archived immediately).

Trigger Consideration for Knowledge Articles

ActionWhich Trigger Context
New Article SavedBefore Insert and After Insert
Existing Draft Articles Saved AgainBefore Update and After Update
Publish ArticleNo
Archive ArticleNo
Edit as DraftBefore Insert and After Insert
Undelete Article From Recycle BinNo
Delete ArticleBefore Delete and After Delete
AssignBefore Update and After Update (Only when the article is edited before being assigned)
Importing ArticlesBefore Insert and After Insert
Importing Articles with TranslationBefore Update and After Update

I hope this will help you when dealing with Knowledge from Apex. If you have any feedback, please post it in the comment section. Thank you.

Share:

Handy SOQL/SOSL Queries for Knowledge

 


Happy Monday!! In my last post, I have explained the Data Model around Salesforce Lightning Knowledge. If you haven't gone through that post, I highly recommend you going through the post "Understanding Salesforce Lightning Knowledge Data Model" as it is going to help you to understand the queries in this post.

Let's first create the article - "Hello World" and below are the different versions with different publishing status. Below article properties which I will be using the query -

  • Article Number: 000001000
  • Knowledge Article Id: kA03t00000063w2CAA













Fetching Latest Knowledge Article Version

SELECT Id,PublishStatus,Title FROM Knowledge__kav WHERE KnowledgeArticleId = 'kA03t00000063w2CAA' AND IsLatestVersion = True


Fetching Published Knowledge Article Version

SELECT Id,PublishStatus,Title FROM Knowledge__kav WHERE KnowledgeArticleId = 'kA03t00000063w2CAA' AND PublishStatus = 'Online'


Fetching Draft Knowledge Article Version

SELECT Id,PublishStatus,Title FROM Knowledge__kav WHERE KnowledgeArticleId = 'kA03t00000063w2CAA' AND PublishStatus = 'Draft'


Fetching Archived Knowledge Article Versions

SELECT Id,PublishStatus,Title FROM Knowledge__kav WHERE KnowledgeArticleId = 'kA03t00000063w2CAA' AND PublishStatus = 'archived' AND IsLatestVersion = False

This one is tricky, as to query Archived article versions, KnowledgeArticleId and IsLatestVersion = False and PublishStatus = archived should be mentioned.

Note -
Using bind variables with Apex SOQL Statements with KnowledgeArticleVersion is not allowed. So you need to use dynamic SOQL like below -
final String ONLINE_ARTICLE = 'Online';
final String myQuery = 'SELECT Id FROM Knowledge__kav WHERE PublishStatus = :ONLINE_ARTICLE';
List<Knowledge__kav> allArtciles = Database.query(myQuery);

Working with DATA CATEGORY

WITH DATA CATEGORY is an optional clause in SOQL and it helps to identify articles linked with one or more data categories.
You can use WITH DATA CATEGORY to fetch articles FROM ObjectTypeName where 
  • ObjectTypeName = KnowledgeArticleVersion to query all articles types.
  • ObjectTypeName = an article type API Name to query a specific article type.
  • ObjectTypeName = Question to query questions.
Note - When ObjectTypeName = KnowledgeArticleVersion or any article type API Name, then WHERE clause is mandatory. You can put one of the below things in the WHERE clause -
  • PublishStatus 
    • "online" to published articles.
    • "archived" to query archived articles
    • "draft" to query draft articles
  • Id = articles Id.
SOQL Query -
SELECT Title FROM KnowledgeArticleVersion WHERE PublishStatus='online' WITH DATA CATEGORY NorthAmerica__c ABOVE canada__c

Note - WITH DATA CATEGORY, only AND logical operator is allowed. 


DATA CATEGORY Filtering Selectors

Let's say we have the below data category structure -
Earth__c
    Asia__c
        India__c
        Bangladesh__c
    NorthAmerica__c
        Canada__c
        USA__c
    Europe__c
        Switzerland__c
        France__c
        German__c

Example 1: Fetch all published articles from Canada 
SELECT Title FROM KnowledgeArticleVersion WHERE PublishStatus='online' WITH DATA CATEGORY Earth__c AT Canada__c

Example 2: Fetch all published articles above German
SELECT Title FROM KnowledgeArticleVersion WHERE PublishStatus='online' WITH DATA CATEGORY Earth__c ABOVE German__c
This will fetch articles linked with German, Europe, Earth data categories.

Example 3: Fetch all published articles below Asia
SELECT Title FROM KnowledgeArticleVersion WHERE PublishStatus='online' WITH DATA CATEGORY Earth__c BELOW Asia__c
This will fetch articles linked with Asia, India, Bangladesh data categories.

Example 3: Fetch all published articles above or below Europe
SELECT Title FROM KnowledgeArticleVersion WHERE PublishStatus='online' WITH DATA CATEGORY Earth__c ABOVE_OR_BELOW Europe__c
This will fetch articles linked with Europe, Switzerland, France, German, Earth data categories.

To know more about, please read this great section here.

Thank you and please let me know if you have any handy queries in the comment section.


Share:

Understand Salesforce Lightning Knowledge Data Model



While working with Lightning Knowledge, what I realized is that there is hardly any tutorial/post which explains the Knowledge Data Model in a very simple way. So I thought of writing my understanding with examples covering the part of the data model. I hope this will help you to understand the data model clearly and quickly.

Understanding the data model is always very important while doing the development as it will help you to play with the objects and do configure/customization that is possible, basically getting the maximum benefit of the platform.

To start with, the Knowledge Object Model is based on Abstract and Concrete objects. 


Core Abstract and Concrete Objects

The core abstract objects are - KnowledgeArticle and KnowledgeArticleVersion. The corresponding concrete versions are - Knowledge__ka and Knowledge__kav.
Below is the data model from the Salesforce Developer Guide -

Complete Data Model 



Relationship between Knowledge__ka and Knowledge__kav

As per the data model, the relationship between Knowledge__ka and Knowledge__kav is 1 to many. That is one Knowlegde__ka can have multiple Knowledge__kav. The link is happening through KnowledgeArticleId (remember KnowledgeArtcileId and Id are two different fields). So let's check the example below.

The "HelloWorld" article is having two versions - 

Now if I run the query against Knowledge__ka, I am getting one entry which provides me the KnowledgeArticleId

Now with the same KnowledgeArticleId, if I query Knowledge__kav, I will get one entry. Surprised?? Why only one entry where it should be two. The reason is that when you publish version 2, version 1 is marked as Archived. So SOQL query will not count the archived versions.


If I create another version and mark that as Draft (not publish), then the query will return two entries like below -

Note - Here is the link -

Knowledge__ka.Id = Knowledge__kav.KnowledgeArticleId

Relationship between Knowledge__kav and Knowledge__DataCategorySelection

Here is the same above document with two DataCategory - India and Canada


Note - Here is the link -

Knowledge__kav.Id = Knowledge__DataCategorySelection.ParentId

Relationship between Knowledge__ka and Knowledge__ViewStat

Knowledge__ViewStat is derived from abstract object KnowledgeArticleViewStat. It is used to store the number of views for a specific article.

The link is -

Knowledge__ka.Id = Knowledge__ViewStat.ParentId

Here is the query 


Relationship between Knowledge__ka and Vote

The object is used to store information about Upvote and Downvote against the article.

The link is -

Knowledge__ka.Id = Vote.ParentId

Here is the query 


I hope this will help you to understand the data model. Please let me know your feedbacks. Thanks.



Share:

Queueable Apex

 


Earlier I wrote a blog post dedicated to Asynchronous processing in Salesforce. This time I will focus on Queueable Apex only.

Queueable Apex is a more advanced version of future methods. It has all the functionalities of the future method along with the power of Batch Apex. So - 

Queueable Apex = Future Method + Batch Apex

It provides additional job chaining and allows for more complex data types.

With Queueable Apex, developers will be able to submit jobs for asynchronous processing, like something future method can do as well. But the difference comes here -
  • Flexibility in method parameters: With Queueable Apex, developers will be able to create classes that will allow member variables of non-primitive data types like sObjects or custom Apex types. 
  • Monitor the progress: Once the developer submits a job by executing the command System.enqueuJob, it provides an ID, which is basically a Job Id. With that Id, the developer can now query the progress either from Salesforce interface in the Apex Job page or by querying the AsyncApexJob table.
  • Chaining jobs: Developer can now chain jobs i.e. starting a new queueable job from an already running queueable job.


Batchable vs Future vs Queueable

Batchable was the first one introduced by Salesforce for asynchronous heavy processing. It was "heavy" in terms of resource usage and also needs longer time to process/complete the work.

To solve the problem with Batchable, Salesforce introduced the Future method. It is lighter on resource and can do all the work which were previously done by Batchable jobs but in a much more efficient way. But the problem with the Future is that it will not return any Job Id, so as a developer, you have no option to figure it out whether the future job is completed or not. At the same time, it has only a limited amount of space to store the data,  that is why Future methods only accept Primitive and collections.

To solve the above drawbacks, Salesforce introduced the third version of asynchronous processing i.e. Queueable Apex. It is lighter than Batchable but gives the Job ID, which can be used to know the progress of the job. It also allows developers to pass non-primitive data types. Basically, Queueable is a hybrid solution between the limited future methods and the resource-heavy Batchable interface.

Important points to remember

  • The execution of a queued job counts once against the shared limit for asynchronous Apex method executions.
  • You can add up to 50 jobs to the queue in a single transaction.
  • With chaining, you can start only one job from an already running job. That means there can be only one child job for a parent job. Staring multiple jobs from an already running job is not possible.
  • There is no depth limit in terms of how deep you can chain jobs. That means you can start a child job from parent one, and then start another job from child one and continue the process unlimited number of times. For developer and trial org, the maximum stack depth for chained job is 5.

Queueable Apex

public class AccountQueueableExample implements Queueable {
public List<Account> accList;
public AccountQueueableExample(List<Account> accList) {
this.accList = accList;
}
public void execute(QueueableContext context) {
for (Account acc : accList) {
// Update the Account Name
acc.Name = acc.Name + 'Technical Potpourri';
}
update accList;
}
}


Call Queueable Apex

List<Account> accList = [SELECT Id, Name FROM Account];
ID jobID = System.enqueueJob(new AccountQueueableExample(accList));


Developer Guide

Share:

New Admin Features From Winter 21 Release



In today's post, I am going to share some of my favorite Admin features from Winter 21 release.

Survey

While creating the survey, admins now have the option of saving the survey as a template. After creating the template, users can open it and make a copy from the top-right menu to create their own survey based on the template.



Flow Enhancements

I have written a separate post covering only flow enhancements coming with Winter 21 release.
Here is the post - Winter 21 Flow Enhancements


Dynamic Form    

With this release, admins now have the power to select the position of the fields in the page layout. As of today, this is only available to custom objects and Lightning App Builder.

When admins will open the record details section from the Lightning page in App Builder, they will be presented with the option to Upgrade (as shown below). Selecting the upgrade option will provide the admins the option to create dynamic forms by positioning fields in different sections on the layout.



Even admins can click on the "Analyze" button at the top right section which will provide them the option whether the customization is good from a performance standpoint.


No More Ref IDs in Email-to-Case

Ref IDs are not always our good friend when dealing with Email-to-Case, as people tend to delete, modify those ugly looking ids when sending emails/replies and that always causes problems with case routing.

The good news is that Ref IDs are going to be phased out. Exact dates will. be announced soon, as there will be an upgrade path to ensure existing Email-to-Case functionalities will still work. After this new features, emails will be matched by information in the email header instead.

As this new feature is coming, I think it is a great time to look out for any automation that exists today in your org which depends on these Ref IDs.

Guest User Access in Communities

Guests users in your communities will be restricted in some of their permissions. This applies to any standard or custom objects with the below permissions -
  • View All Data
  • Modify All Data
  • Edit
  • Delete
If in your community implementation today, you are allowing your guest users to edit existing data, then this is the time when you should consider converting them to community users.

Improved Email Template Creation

Now admins can create email templates by drag and drop functionality. This drag and drop template builder is similar to the page builder and definitely provides a great enhancement to the way we all create email templates today.

Admins can create email templates by going to the "Email Templates" tab and clicking on the New button.


Please let me know your favorite admin features. Enjoy Winter 21 release.



Share:

How to update "N" records in Flow

 



If you are implementing business logic through Salesforce's flow, you might need to loop through a list of records to do some manipulation. This is a very basic requirement. 

If you ever need to query records from Salesforce (let's say all accounts where the billing country is India), it is very easy to do in SOQL and Get Records flow elements. But things will become a little tricky when the requirement says "Fetch first 5 accounts based on the created date where the billing country in India". It is definitely very easy in SOQL with the limit statement, but in Get Records flow element, there is no way to (as of Winter'21 release) limit the record.

To overcome this situation, we can implement the counter mechanism which will basically make sure that when the # of loop iteration is greater than 5 (because we just need the first 5 accounts), the flow will not perform any business logic.

Here is the overall flow -



Here as you can see for each loop iteration, we are incrementing the counter value by 1 and then checking whether the new value is greater than 5 or not. Based on that decision element, either we are updating the account's rating i.e. performing business logic or ignoring the business logic execution. This flow solution is definitely making sure that only for the first 5 records the business logic is getting executed.

But do you see the problem? What will happen when there are let's say 1000 accounts satisfying the condition i.e. BillingCountry = India? In that case, the above solution will update the rating for only the first 5 accounts, but the loop will still execute for another 950 times (for the remaining 950 accounts). First of all, this 950 times loop execution is unnecessary and chances are there that it will throw limit exception.


So what is the solution?

Let me show you how to build the solution

Step 1

Copy the list of accounts fetched into a record collection variable. Include this component right next to Get Records element as shown below


Step 2

Update the loop element to make sure that it is using the newly created record collection variable, not the original collection variable generated from Get Records element. This is super important and the key to this solution.



Step 3

Store the updated accounts in a new collection variable and place it right next to the element where the account rating is getting updated. This is shown below as -

Step 4

Update the collection variable to empty when the counter value will become greater than 5. This will make sure that loop will not execute any further. 



That's all you need to do to make sure your loop is only iterating N number of times only. I hope this solution will help you to make your loop optimized. Please provide your comments. Thank you.


Share:

Winter '21 Apex New Feature

 


This post will cover some of my favorite Apex new features from Winter '21. I have published another post that covered new existing enhancements for Flow Designer. To explore all the new features from Winter '21 release, I highly recommend -
  • Sign up to a pre-release org and explore all the new features.
  • Post your findings in the Trailblazer Community and include the hashtag #Winter21Treasure to receive Trailhead Treasure Hunter badge
Here is the list

Safe Navigation Operator

Share:

Winter '21 Flow Enhancements

 


Winter '21 pre-release org is ready. And without any surprise, Winter '21 is also bringing lots of great enhancements. In this post, I am going to focus on a few Flow Enhancements that we will be getting soon and will be able to take advantage of. 

Handling Deletion Through Record Triggered Flow

Share:

Show Your Data in Datatable, Map or Tile Format Inside Flow


In this post, I am going to show you one of the most powerful AppExchange flow solutions built by Salesforce Labs. If you ever needed to display a collection of records in some format, mostly in datatable format to the user and provide options to the user to select records from that list and finally perform some actions based on those selected records, then this AppExchange pre-built flow solution is your going to be your friend. ūüėÉ

The name of the solution is Flow Datagrid Pack. With this solution, you have the power now to display your collection of records in three different formats -

  • Data Grid - Basically displays the records in a multi-select datatable.
  • Tile Grid - Displays in multi-select (configurable) tiles format.
  • Map Grid - Displays multi-select markers on map where you need to display records on the map. Ex: Display a list of accounts in Ontario within the map.
Let's configure this flow solution for a basic use case.

Use Case:

Need a solution where all the contacts from an account will be displayed in datatable and the user can select from the list. Based on the selected contacts, only those contacts should be displayed on the next screen.

Solution - Flow:

I build the below flow using the Flow Datagrid pack.

Here are the steps -

Fetch Associated Contacts

In this step, I am fetching all the contacts associated with an account.

Loop Through All Contacts and Store Contact Ids

Here I am looping through all the contacts and storing their ids in a collection variable. This step is needed as a collection variable with record ids are needed in the Flow Datagrid Pack to display the records. 
Note - I am not sure why this extra loop is required, but my initial thought is that this loop can easily be removed and Flow Datagrid Pack should work on the collection of records.


Display All Contacts in Datatable

Here I am using the Flow Datagrid Pack pack as displayed below.
To start with, I am just using the basic input parameters, but you can configure a lot. The details level of the configuration details, you can get to know from here.
  • ID List: Here I am using the collection variable I have created in an earlier screen which stores all the contact ids.
  • Object API Name: I am using Contact here as object name. You can literally work on any standard or custom objects. Note - With External objects, this solution is not working as of today.
  • Field API Names: I am using the API names of the fields which I would like to display inside the datatable.

Display Selected Contacts

In this step, I am displaying the selected records using the same Flow Datagrid Pack. 
The difference is that here in the ID list I am using the auto-generated collection variable from the previous screen which stores the id of only selected contacts.



This is how the flow will look like -

That's all!! Isn't it super easy? I highly recommend everyone to try this one. 

Note - To get all the pre-built cool Flow solution check the dedicated flow section in AppExchange. Link

Share:

Spring'20 Brings Improved Code Coverage Result for Apex Test Class

 

Writing test classes to cover both positive, negative, and bulkified scenarios are always the best practices that each developer should follow. While writing test classes, our approach should be to cover as much as code and all the scenarios. There is a restriction from Salesforce that if there is not enough coverage (75%) for the code, then Salesforce will not allow you to deploy your code to production.

So identifying the code coverage is very important. Now there are multiple ways we can get to know the code coverage like - Setup menu, Developer Console, SOQL Query, Salesforce CLI, or Salesforce extension in Visual Studio Code. With so many options there comes the difficulties. Each option presents the code coverage in a different way and more importantly, each option calculates code coverage in a different way. This always creates confusion. For example, when a developer writes the test class and executes that from CLI, it provides the code coverage, let's say 90%, which should be good enough to deploy the code into Production. But while deployment, the code coverage came down to 50%, and thus deployment stops. The reason for this drop in code coverage is that while deploying code coverage is calculated at the org level i.e. percentage of coverage for that class across the org.

To solve this problem, Salesforce comes up with the Enhanced Code Coverage option. With this option, developer will get - 

  • Different classes being covered by the test class. The percentage of each class covered and uncovered lines from each class.
  • Test result which will pass/fail result for each test method.
  • Finally Test Summary will show "Test Run Coverage" and "Org Wide Coverage".
This change was introduced in Spring 20 release. You can read more about it - https://releasenotes.docs.salesforce.com/en-us/spring20/release-notes/rn_sf_cli_code_coverage_apextests.htm

In order to use this feature in Salesforce CLI, the first thing you need to do is set up your environment variable.

Setting up the environment variable

There are three ways to do that. 
You can do that for a single command by doing 

SFDX_IMPROVED_CODE_COVERAGE=true sfdx force:apex:test:run ...

or set it for a shell session with

export SFDX_IMPROVED_CODE_COVERAGE=true

or if you want to set it permanently, then set it in the config file for your shell/command prompt.

Setting up the environment variable is important as it will eliminate Developer Console and VS Code/CLI code coverage mismatch.

Running the test

Once the environment variable is set up, you can run your test by -

sfdx force:apex:test:run -n "CommunicationHandlerTest" -c -r human

Here I am trying to execute the test class - CommunicationHandlerTest. To know more about the options, read - https://github.com/forcedotcom/salesforcedx-vscode/issues/2224

The result will be something like this 

I highly recommend everyone to use this new feature. Thank you.

Share:

Spring'20 brings one Invocable method for all

 

Have you ever asked this question to yourself - Why I have to write multiple invocable methods for the same functionality working on different objects? Definitely not a very clean approach. Thankfully Salesforce came up with the enhanced version of Invocable methods which now can work on multiple objects doing similar types of work. 

With this new enhancement, you can now write Invocable methods which will accept generic sObject data type. As a result, you will write one single Invocable method which will now work for multiple sObjects. The advantage is that if in your org, you have multiple Invocable methods doing similar operations (you just created them because they need to work on different sObjects), it the time to merge them to make a single Invocable method and make your org look clean.

In this post, I am going to show the example of creating one Invocable method which will be used to create Lead and Account when calling from different flows.

Here is the Invocable method:

public class createRecords {
@InvocableMethod(
label = 'Create Records'
description = 'Update records or create new records')
public static List<myResponse> createRecords(List<myRequest> request){
List<SObject> records = new List<SObject>();
for(myRequest singleRequest : request){
records.addAll(singleRequest.records);
}
List<myResponse> response = new List<myResponse>();
myResponse singleResponse = new myResponse();
Schema.SObjectType sObjectType = records.get(0).getSObjectType();
if(sObjectType != null){
String listType = 'List<'+sObjectType+'>';
List<SObject> castRecords = (List<SObject>)Type.forName(listType).newInstance();
castRecords.addAll(records);
upsert castRecords;
singleResponse.records = castRecords;
response.add(singleResponse);
}
return response;
}
public class myRequest {
@InvocableVariable(label = 'Records to create')
public List<SObject> records;
}

public class myResponse {
@InvocableVariable(label = 'Inserted/Upserted records')
public List<SObject> records;
}
}

As you can see, this above Apex code is written in such a way that it can work on any sObjects. In the actual Invocable method, we are typecasting the input records (myRequests -> records) to the actual sObject.

Below are two flows from where I am going to call this Invocable method passing the type of sObject against which the function needs to work.

Account Create Flow



Lead Create Flow




As you can see in both the flows, I have used the same Invocable method, just method the sObject name against which it will operate. I think this enhancement is going to make development very clean, reducing the surface area od code maintenance and increasing code reusability. 
Share:

Never miss a post. Subscribe to get latest blog posts, right into your email box.

* indicates required

Labels

Salesforce (105) Apex (52) admin (28) visualforce (21) ADM (20) dev 501 (19) lightning (19) integration (18) learn salesforce (18) 501 (16) javascript (14) SOAP (13) tutorial (11) Advanced Apex (10) Certification. (10) Kitchener Developer Group (8) Trigger (8) test class (8) Certification (7) flow (7) security (7) unit testing (7) Advanced Admin (6) Lightning Experience (6) SOQL (6) Sharing and Visibility (6) design pattern (6) developer (6) report (6) salesforce release (6) service cloud (6) trailhead (6) use case (6) Lightning Feature (5) New Features (5) css (5) dashboard (5) debug (5) formula (5) mobile (5) solution management (5) JSON (4) Kitchener User Group (4) Knowledge Management (4) Lightning Web Component (4) New Feature (4) Sales Cloud (4) Salesforce DX (4) Tips (4) WebSphere (4) best practice (4) cast iron (4) component (4) deployment (4) event (4) github (4) html (4) map (4) polymer (4) profiles (4) release (4) responsive (4) tdd (4) ui (4) visual studio code (4) Architect (3) Article (3) Live Chat (3) Online Event (3) Opportunity (3) Performance (3) Products (3) REST (3) Role (3) SOSL (3) Salesforce Certification (3) Scratch Org (3) Spring 20 (3) Study Notes. (3) Summer15 (3) VS Code (3) Web Technology (3) Winter21 (3) automation tool (3) configuration (3) dynamic apex (3) license (3) mapbox (3) singleton (3) version controlling (3) AppExchange (2) Asynchronous Apex (2) Asynchronous callout (2) Aura Framework (2) Bulkify (2) Community (2) Data Architecture and Management Certification (2) Devops (2) Distributed Version Controlling (2) ES6 (2) Eclipse (2) Einstein (2) Enhancement (2) Enterprise Territory Management (2) Financial Services Cloud (2) Force.com IDE (2) Governor Limit (2) Groups (2) IBM (2) Implicit Sharing (2) JourneyToCTA (2) LWC (2) Lightning Design System (2) Live Agent (2) Metadata (2) PD II (2) Price Book (2) Queueable (2) SFDX (2) Sharing (2) Spring 15 (2) Summer17 (2) Territory (2) Virtual Event (2) ant (2) basic (2) chatter (2) code coverage (2) coding (2) communication (2) console (2) controller (2) documentation (2) dreamforce (2) git (2) jquery (2) logging (2) object (2) permission (2) process builder (2) salesforce1 (2) strategy (2) visual workflow (2) xml (2) Action Plan (1) Action Plan Template (1) Activity Timeline (1) Advanced Currency (1) Agent Productivity (1) Analytics (1) Apex Sharing (1) Arrow (1) Batch (1) Bots (1) Browser (1) Bulk data load (1) CTA (1) Calendar (1) Canon (1) Case Management (1) Celebration (1) Cheat Sheet (1) Classic (1) Compare (1) Confetti (1) Constructor (1) Contact Center (1) Continuation (1) Continuous Integration (1) Convert (1) Cookie (1) CumulusCI (1) Custom Metadata (1) Custom Object (1) Custom Permission (1) Customer (1) Data Model (1) DataCategories (1) DataGrid (1) DataTable (1) Dated Exchange Rate (1) Decorator Design Pattern (1) Dev Hub (1) Development (1) Diwali (1) EDA (1) ESLint (1) Education Cloud (1) Email (1) FSC (1) Function (1) Future (1) Global Gathering (1) Goals (1) Guest Access (1) Guest Profile (1) Guest User Sharing Rule (1) Guide (1) HEDA (1) Higher Education (1) Household (1) Husky (1) IDE (1) Ideas (1) Improvement (1) Invocable (1) KPIs (1) Knowledge (1) Large Data Volume (1) LastModifiedDate (1) Lightning Knowledge (1) Manage Currencies (1) Manual Sharing (1) Metrics (1) Multi Currency (1) New (1) OOPS (1) OWD (1) Omni-Channel (1) Optimize (1) Partner (1) Permission Set (1) Person Account (1) Photo (1) Pipeline (1) Platform Developer I (1) Platform Developer II (1) Presentation (1) Prettier (1) Product Schedule (1) Profile (1) Promise (1) Prototype (1) Public Site (1) Query Plan (1) QuickReference (1) Related records (1) Reports (1) Retrieve (1) Role Hierarchy (1) SAL (1) Salesfor (1) Salesforce Advisor Link (1) Salesforce Labs (1) Salesforce Optimizer (1) SalesforceDx (1) Schedule (1) Session (1) Sharing Rule (1) Sharing Sets (1) Site (1) Skills (1) Snap-ins (1) Spring 17 (1) Summer14 (1) Summer16 (1) Summer19 (1) Switch (1) SystemModStamp (1) Tile (1) Timeline (1) Unauthorized Access (1) User License (1) Users (1) Validation Rule (1) Web (1) Webservice (1) Winter'15 (1) Winter'17 (1) access (1) actionFunction (1) actionPoller (1) actionRegion (1) actionSupport (1) agile (1) app (1) approval process (1) aura (1) awesome (1) backup (1) bitbucket (1) book (1) campaign (1) change set (1) cli (1) code (1) csv (1) custom button (1) custom settings (1) customization (1) data loader (1) database (1) delegate Admin (1) describe (1) dom (1) duplicate (1) dynamic (1) dynamic form (1) email template (1) email-to-case (1) equals (1) error (1) field-level security (1) folder (1) ftp (1) generic (1) gift (1) global describe (1) hashcode (1) import wizard (1) jenkins (1) keynote (1) long running requests (1) monitoring (1) mysql (1) page layout (1) personal (1) power of one (1) record type (1) relationship (1) request (1) review (1) solution (1) sub-tab (1) survey (1) tab (1) username (1) workflow (1)

Popular Posts

Total Pageviews

Contact Me

Name

Email *

Message *