A blog dedicated to Salesforce Ohana

How to choose between Trigger and Lightning Process Builder

With the introduction of Lightning Process Builder, we can do many things which were kind of limitations of Workflows. Salesforce introduces Lightning Process Builder as successor of Workflow rules, thus allowing more config options through click and reducing amount of apex customization required. Process Builder supports all the features from Workflows with the exception of sending outbound message without apex code. I will not be surprised if Salesforce decides to decommission Workflow in near future.

Previously there were few scenarios (listed below) which were not possible through workflow and we need to write Apex trigger to achieve those. Here are few of them -

  • If we need to perform complex validation
  • Before/After logic for record insert/update/delete/undelete operation.
  • Update/insert any objects or related records.
Problem with workflow is we can't update child records with workflow. Workflow supports only updation of parent record. So earlier we need to go for Trigger. But with the introduction of Process Builder, now we can update child records as well. Below is one case study -

Case Study:
It's a library management system - Universal Library. Library is having many books. If the book is not available, user will send the request for the book. The moment book is available, all the request status will change from 'Hold' to 'Ready to Pickup'. To achieve this below is the object model -
Here Book and Book Request are connected through Master-Detail relationship. Previously to achieve this requirement, we need to write Apex classes. But now we can do the same with Process Builder. Below is the screenshot of Process Builder -

With Process Builder you can add conditions to update selected records. For example, if library is having membership types - Gold, Silver, Broze, once a book is available, update only those requests which came from Gold membership holder and make them "ready to pickup".

There are few situations(sending outbound message) which can't be handled through config in Process Builder. For that, we need to write Apex class/method. We need to make sure your method is annonated with @InvocableMethod so that it can be used in Process Builder. With Invocable methods, there are few limitations, which we need to keep in mind. Limitations can be found @ https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_annotation_InvocableMethod.htm

Excited, right!! If you want to convert existing Apex Trigger to Process Builder, please keep in mind the below points -
  •  You need to make sure that in your trigger any field update is not used by subsequent trigger or workflow. The reason behind is that execution order wise Process Builder will execute after workflow rules.
  • With enabling Recursion option in Process Builder, one record can be reevaluated maximum 5 times. So you need to make sure you are not disturbing Salesforce limits here.
Scenarios where Trigger is the best approach:
There are still scenarios where Apex Trigger is the best approach. I am trying to write down few of them. If you have anything in your mind or faced any issues during your development for which you have moved to Apex Trigger, please feel free to let me know. I will be more than happy to include those scenarios.
  • Complex Validation Rules in not possible with Process Builder. You need to got for Apex trigger to achieve that. Here is the Salesforce Idea to add Validation rule capability in Process Builder - Salesforce Idea.
  • Apex Trigger's context - Delete/Undelete with before/after even is not possible with Process Builder.
I will really appreciate if you provide your feedback. Thanks.

How to choose correct Process Automation tool || Process Builder vs. Visual Workflow vs. Workflow vs. Approval Process

With process automation, we now have multiple solutions available which we can use to implement the requirements. The solutions that we have are -
  • Lightning Process Builder
  • Visual Workflow
  • Workflow
  • Approvals
With so many options, it brings responsibilities as well to the developer to decide which tool to use. In this post, I will try to provide a comparative study on which tool is best based on some situations. But at the end, it is upto you as a developer to decide and select the best tool available. I hope this post will help you to take the decision.

Let's start with the easy one -

Approval Process ::
As the same suggests, whenever you need to take approval actions, you need to go for Approval process. This is an automated solution which will work based on the record creation or record value change. 
Below are few important points about approval process -
  • Complexity of Approval process is very simple. It can support only one if/then statement.
  • It doesn't support time-based approval process i.e. trigger the approval after 24 hours or something like that. It is a complete real-time solution.
  • Approval process can't call Apex code or delete any records.
  • But Approval process can create only Tasks (nothing else).
  • Approval Process can update the same record or it's parent.
Workflow :;
Workflow is the automation tool which should be used when you need to take action based record creation or record's value change. 
Below are few important points about Workflow -
  • Workflow rule works when the record is created or when the record's value is changed.
  • It supports time-based action i.e. workflow rule action can trigger after 24 hours since the value of the record changed to meet the criteria.
  • Complexity is again very simple i.e. single if/then statement.
  • It can create only task record.
  • It can't delete any records.
  • It can send outbound message without code. [This is very important factor to choose Workflow over Process Builder]
  • It can't invoke approval process.
  • It can update the same record or it's parent record. It can't update child record. [This is a limitation of Workflow and Process Builder can handle this limitation]
Visual Workflow ::
People sometimes refer Visual Workflow as "Flow". This automation tool will come into picture when you need to take some input from end user and based on the input you need to take the decision. Visual workflow is very powerful and as always with power, it brings complexity as well.
With Visual Workflow, developer can call apex, create/update/delete records, post to chatter, send emails, submit for approval. It supports time-based action as well. The only limitation with Visual workflow is that it can't send outbound messages without any code.

Process Builder ::
Process Builder is really a powerful automation tool. With Process Builder, developer can easily automate business process using graphical representation. It comes with two parts -
  • Criteria which will decide when the Process Builder will kick off.
  • Immediate or Scheduled actions which will happen when the Criteria will meet.
Below are few important points about Process Builder-
  • With Process Builder, you can create records, but you can't delete any records.
  • You can update any related records (be it with Parent or be it with Child).
  • You can submit for approval as well.
  • You can't send outbound messages without code.
  • You can launch a flow - auto launched flow. 
With all these understanding, I have prepared a small decision tree which will help you to decide the correct automation tool. 

Please provide your feedback. Thanks.

Dynamic Apex - Build Dynamic SOQL and SOSL

This post is the continuation of my previous two posts on Dynamic Apex. You can find the posts here
In this post, I will explain another very powerful feature of Dynamic Apex i.e. Dynamic SOQL and SOSL.

Dynamic SOQL:
Dynamic SOQL refers to the ability of creating SOQL statement in runtime with Apex code i.e. you can select which fields you want to query based on situation or user input and then prepare the SOQL statement and finally perform the query to fetch the data from the organisation.

You can execute the below statement to perform the query:

Dynamic SOQL can return concrete sObjects i.e. Account, Lead or MyCustomObject__c or the generic sObject data type. At runtime, system will match the return type with the variable's declared type. If the types are not matching, then runtime will be thrown. So it is the responsibility of the developer to cast from generic sObject data type to a concrete sObject.

In terms of governor limits, Dynamic SOQL queries have the same governor limits as static queries.

Below example is going to fetch the fields from Account sObject, prepare the SOQL statement and then finally query Account sObject to fetch the data.

Dynamic SOQL Consideration:
In Dynamic SOQL, you cannot use bind variable strings in a query string. For example, the below section of code will not work and will throw an error that Variable doesn't exist.

To solve that you need to resolve the variable into a String variable and then use in Dynamic SOQL. Below is the code which will work.

Dynamic SOSL:
With Dynamic SOSL, developer can create SOSL statement in runtime thus allowing to build more flexible applications.

You can execute the below statement for dynamic SOSL:

Dynamic SOSL statement returns a list of lists of sObjects, where each list contains the search result for a particular sObject type. Results will be stored in the same order as the sObjects are specified in the dynamic SOSL query. Dynamic SOSL can't be used where an inline SOSL can be used, such as in regular assignments and for loops.

Dynamic SOSL is also having the same governor limits as static SOSL statements.
Below code will search for the keyword in the object - Account, Lead, Contact and sudipta__Book__c.

Please provide your feedback. Thanks.


Dynamic Apex - Playing with CRUD and FLS

Security is one of the important things in today's world. And when we talk about cloud, Security is the top most priority items. No doubt. Salesforce is not an exception and they are also considering Security really seriously.

In Salesforce, we have different types of Security controls - starting from org level security to object level, followed by record level and field level. This post focuses on methods for controlling data at the object and field level.

As always I always believe explaining concept with examples is the best and effective way. Today also I will do the same thing.

For this post, I have prepared a small object called Book and below is the detail -

Important Note -

In Visualforce, when you use any sObject or sObject field, the platform will enforce CRUD and FLS automatically. If the user is not having FLS to a field, Salesforce will automatically remove the field from the Visualforce page. For example, apex:inputField tag will be rendered as read-only for those fields having FLS set as read-only. But the exception here are the tags apex:inputText, apex:inputTextArea. Using these tags tells Visualforce to not treat them as sObject field, thus platform will not automatically enforce FLS for those  fields.

Apex Code to check CRUD manually:
Write a Visualforce page with controller behind which should display all Books present in the org in the form of Picklist. When we will execute the page with user having access to Book object, it should work fine, but when we will execute the same page with user having no access to Book object, we want the page to display an error message - "SORRY!!! USER IS NOT HAVING ACCESS.."(Instead of some Salesforce error message).

To implement this one, in my developer org, I have two profiles. One having CRUD access to Book object and another having no access at all. Below are the details -

VisualForce Page:
<apex:page controller="BookSelector">
    <apex:form >
        <apex:outputLabel rendered="{IF(hasAccess==false,true,false)}" value="{!errorMessage}"/> 
        <apex:pageBlock rendered="{IF(hasAccess==true,true,false)}">
            <apex:pageBlockSection title="Book Selector" collapsible="true" columns="1">
                <apex:pageBlockSectionItem >
                    <apex:outputLabel value="Select the book here: "/>
                    <apex:selectList value="{!selectedBook}" size="1" multiselect="false">
                        <apex:selectOptions value="{!allBooks}"/>
public with sharing class BookSelector {
    public String selectedBook{get;set;}
    public String errorMessage{get;set;}
    public Boolean hasAccess{get;set;}
    public BookSelector(){
        //Check if user is having access to the object
            errorMessage = 'SORRY!!! USER IS NOT HAVING ACCESS..';
    public List<SelectOption> getAllBooks(){
        List<SelectOption> options = new List<SelectOption>();
            List<sudipta__Book__c> allBooks = [SELECT 
                                               FROM sudipta__Book__c ];
            for(sudipta__Book__c singleBook : allBooks){
                options.add(new SelectOption(singleBook.Name, singleBook.Name));
        return options;

In the controller, I am using sudipta__Book__c.sObjectType.getDescribe().isAccessible() method to find out whether the current user is having read access to the Book object. If not, I am setting up the custom error message (Ideally this message should come from Custom Label).

Take away:
The method sObjectName.sObjecType.getDescribe().isAccessible() will return whether the user is having read access to this object.
Similarly we can use isCreateable(), isDeletable(), isUpdateable() methods to find out create, delete and edit permission.
You can find the all the methods @

CRUD and FLS check manually in Visualforce Page:
You can check whether you have CRUD permission for sObject or FLS permission for sObjectField
in Visualforce page as well. You can do that with the help of $ObjectType element.

For example, below Visualforce statement will not execute if the running user is not having View permission to see the Contact Name field.

<apex:outputText value="{!contactName}" rendered="{!$ObjectType.Contact.fields.Name.Accessible}" />
Similarly, the below command button will not even render if  the running user is not having Updateable permission on custom book object.

<apex:commandButton action="{!CustomUpdate}" rendered="{!$ObjectType.sudipta__Book__c.Updateable}" />

Please provide your feedback. Thanks.



Follow Me

Enter your email address:

Delivered by FeedBurner

Popular Posts


Salesforce (105) Apex (44) admin (27) ADM (20) visualforce (20) dev 501 (19) integration (18) learn salesforce (18) 501 (16) SOAP (13) lightning (12) tutorial (11) Certification. (9) javascript (8) Trigger (7) test class (7) unit testing (7) Sharing and Visibility (6) design pattern (6) report (6) security (6) trailhead (6) Advanced Admin (5) Certification (5) New Features (5) SOQL (5) css (5) dashboard (5) debug (5) developer (5) formula (5) mobile (5) salesforce release (5) service cloud (5) solution management (5) use case (5) JSON (4) Kitchener Developer Group (4) Lightning Experience (4) WebSphere (4) best practice (4) cast iron (4) component (4) deployment (4) github (4) html (4) polymer (4) profiles (4) responsive (4) tdd (4) ui (4) Advanced Apex (3) Architect (3) Live Chat (3) Performance (3) Products (3) Role (3) Sales Cloud (3) Salesforce DX (3) Scratch Org (3) Study Notes. (3) Summer15 (3) Tips (3) Web Technology (3) dynamic apex (3) event (3) license (3) map (3) mapbox (3) singleton (3) version controlling (3) Bulkify (2) Data Architecture and Management Certification (2) Distributed Version Controlling (2) ES6 (2) Eclipse (2) Einstein (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) Lightning Design System (2) Live Agent (2) Metadata (2) Online Event (2) Opportunity (2) Price Book (2) REST (2) SOSL (2) Sharing (2) Spring 15 (2) Summer17 (2) Territory (2) ant (2) automation tool (2) basic (2) chatter (2) coding (2) communication (2) console (2) controller (2) documentation (2) flow (2) git (2) jquery (2) logging (2) object (2) permission (2) process builder (2) release (2) salesforce1 (2) strategy (2) xml (2) Action Plan (1) Action Plan Template (1) Agent Productivity (1) Analytics (1) Apex Sharing (1) Arrow (1) Asynchronous callout (1) Aura Framework (1) Bots (1) Browser (1) Bulk data load (1) CTA (1) Calendar (1) Canon (1) Case Management (1) Cheat Sheet (1) Classic (1) Community (1) Constructor (1) Contact Center (1) Continuation (1) Continuous Integration (1) Convert (1) Cookie (1) Custom Metadata (1) Custom Object (1) Customer (1) Decorator Design Pattern (1) Dev Hub (1) Devops (1) Diwali (1) Email (1) FSC (1) Function (1) Goals (1) Guide (1) Household (1) Ideas (1) Improvement (1) KPIs (1) Kitchener User Group (1) Large Data Volume (1) LastModifiedDate (1) Lightning Web Component (1) Manual Sharing (1) Metrics (1) New (1) OOPS (1) OWD (1) Omni-Channel (1) Partner (1) Person Account (1) Photo (1) Platform Developer I (1) Presentation (1) Product Schedule (1) Profile (1) Promise (1) Prototype (1) Public Site (1) Query Plan (1) QuickReference (1) Reports (1) Retrieve (1) Role Hierarchy (1) SFDX (1) Salesforce Optimizer (1) Session (1) Sharing Rule (1) Sharing Sets (1) Site (1) Skills (1) Snap-ins (1) Spring 17 (1) Summer14 (1) Summer16 (1) Switch (1) SystemModStamp (1) User License (1) Users (1) Webservice (1) Winter'15 (1) Winter'17 (1) access (1) agile (1) app (1) approval process (1) aura (1) awesome (1) backup (1) bitbucket (1) book (1) campaign (1) change set (1) code (1) code coverage (1) configuration (1) csv (1) custom button (1) custom settings (1) customization (1) data loader (1) database (1) delegate Admin (1) describe (1) dom (1) dreamforce (1) duplicate (1) dynamic (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) sub-tab (1) tab (1) username (1) visual workflow (1) workflow (1)

Total Subscribers

Total Pageviews