Thursday, June 13, 2019

Accessing Parent Field Values from sObjects in Dynamic Queries Using Dynamic Apex

In case of dynamic queries, we often store queries output in sObject and then refer field values. In order to refer field values, we first type cast generic sObject into specific objects like Account, Contact or custom objects as mentioned below:

string qString = 'Select id, name from Account Limit 1';
sObject sb = database.query(qString);
Account acc = (Account)sb;
string accountName = acc.Name;

Suppose we know the field API names then we can utilize the concept of sObject to get field values directly without type casting as mention below:

string qString = 'Select id, name from Account Limit 1';
sObject sb = database.query(qString);
string accountName = sb.get('Name');

So now with the help of sObjects concept, we can access parent field values from child records.

Now consider a scenario in which I have list which stores all field API names which can be used to query opportunity line items. I will generate the dynamic query and will use concept of sObject to access Opportunity fields from sObject which is output of dynamic query.

List<string> fieldAPINamesList = new List<string>{'Id','Opportunity.Name','Opportunity.Partner__r.Name'};
string qString ='Select '+string.join(fieldAPINamesList,',')+ ' from OpportunityLineItem where id=\'00k90000002z4ml\'';
system.debug('****qString:'+qString);
sobject sb = database.query(qString);
//syntax to get OpportunityLineItem Id  value from sObject
string OpportunityLineItemId = string.valueof(sb.get('Id'));
system.debug('******OpportunityLineItemId:'+OpportunityLineItemId);
//syntax to get Opportunity.Name field value from sObject
string OpportunityName = string.valueof(sb.getSobject('Opportunity').get('Name'));
system.debug('******OpportunityName:'+OpportunityName);
//syntax to get Opportunity.Partner__r.Name field value from sObject
//If partner field in opportunity is blank then you will get null pointer exception
string partnerName = string.valueof(sb.getSobject('Opportunity').getSObject('Partner__r').get('Name'));
system.debug('******partnerName:'+partnerName);

Note: While accessing the parent record details in child to parent query, you will get null pointer exception if parent is blank in child record.

I have written an utility method which takes sObject and fieldAPIName as a parameter and returns field value. Please refer below code for reference:

If you run above script in developer console by specifying correct opportunityLineItem Id, then you will see below logs:


Hope this will help!!!

Thursday, June 6, 2019

Fire Platform Events from Batch Apex using Database.RaisesPlatformEvents Interface

With Summer'19 release (API version 44 or later), now it is possible to fire platform events from batch apex. So whenever any error or exception occurs, you can fire platform events which can be handled by different subscriber.

Batch class needs to implement "Database.RaisesPlatformEvents" interface in order to fire platform event.

global class SK_AccountProcessBatch implements Database.Batchable<sObject>,Database.RaisesPlatformEvents{
   //batch logic
}

To understand more about platform events please refer below links

Platform Events : Way to Deliver Custom Notifications within Salesforce or to external Application

Here I will be writing simple batch class which process account records and if any errors occurs during update, then all account record Ids will be published using platform event.

I have created platform event with below mentioned fields:


Below is batch apex code which will fire platform event and I wrote a trigger which will subscribe to platform event.

I have used Database.Stateful interface to store the record ids which are getting failed in each batch execution. In finish method, I am firing platform event with all failed records Ids.

Below is logs generated by trigger which will get executed whenever platform event is fired.


In order to see debug logs for platform events subscription, add a trace flag entry for the Automated Process entity in Setup. The debug logs aren’t available in the Developer Console’s Log tab.

Navigate to SetUp --> Debug Logs --> New
  • For Traced Entity Type, select Automated Process.
  • Select the time period to collect logs and the debug level.
  • Click Save.
I have also created a lightning component which will subscribe to platform events and will display the event message as shown below in snapshot:

Please refer below link to understand how to use platform events in lightning components:

Handling Platform Events in Lightning Components


Hope this will help!!!


Saturday, June 1, 2019

How to Get List of All Child Records for Given Parent Records in .csv File using Apex

If we have lot of child object for a parent object, then it becomes very difficult to find out list of all related records for a given parent. For example, Account and Contact is reference by many standard and custom objects.

Consider a scenario in which Account is parent for more than 50 objects. In this case if we have to check if account record is being reference in any of these child objects, then how we are going to do that.  Its very difficult to add all related list on account page layout or to write SOQL queries to get this information.

If we use nested queries as mentioned below, then we have limit to use only 20 nested queries.

select id, (Select id from Cases),(Select id from Contacts) from Account where Id='0010000xxxxxxx'

In order to overcome these issues, I have written a script which you can run in developer console and you will receive email with .csv file containing all child records for a given parent record.

In below mentioned script, specify the object API name and 15 or 18 digit record id.

After running this script, you will receive .csv file in email as shown below:


If you are getting below mentioned error, while running the script, the make note of below points:


  • This exception can not be handled by try and catch
  • SOQL is not performing well may be because the large volume of data or due to indexing issues on table.
  • Instead of running this script developer console, use batch apex to run this logic. You can create a custom object and first run a script to store all child objects details like relationship name, child object name. Then you can execute the logic in batch class to first fetch all these records from custom object and then fire nested queries by using relation names and store output in variable. Make sure your batch size is not greater than 20 as we have limit of 20 nested queries in SOQL. In finish method write send email code to get .csv file. If you are still getting this error, then keep on reducing the batch size.
Hope this will help!!

Looking forward for your comments and suggestions.



Thursday, May 30, 2019

How to get all Child Objects List along with Relationship Names related to Parent Object using Apex

Sometimes it is required to get the list of all child relationship names in order to identify all related child objects to a parent object.

Dynamic apex helps to find out all related child object. Suppose you want to find all related object for Account then use below code snippet:



You can specify any object API name and run this code snippet in developer console.

You can also use workbench to find out list of child objects. Navigate to Info tab and select Standard & Custom Objects.


Hope this will help!!

Sunday, May 19, 2019

Lightning:NotificationsLibrary : Easy Way to Display Toast or Notices in Lightning

In order to display the toast messages, we have to fire standard event "force:showToast". Now Salesforce recommend using lightning:notificationsLibrary for displaying messages in lightning via notices and toasts.

Toast helps in providing information about status on user action.
Notices helps in displaying the system related issue or update about any maintenance.

NotificationsLibrary makes very easy for developer to display notices and toast.

How to display Notices using lightning:notificationsLibrary

Below is sample code:


How to display Toast using lightning:notificationsLibrary

Below is sample code:

Hope this will help!!!

Thursday, May 16, 2019

Handling Platform Events in Lightning Components

The lightning:empApi component gives methods for subscribing to a streaming channel and listening to event messages. It supports all streaming channels including channels for platform events, pushTopic events and Change Data Capture events. The lightning:empApi component uses a shared CometD connection.

Note:
  • This component is available in 44.0 api version or later.
  • This is available in Lightning Experience and only supported in desktop browsers.
To call the component's methods, add the lightning:empApi component inside your custom component and assign an aura:id attribute to it.

If you want to learn more about platform events then refer below blog:

Platform Events : Way to Deliver Custom Notifications within Salesforce or to external Applications

I have created a lightning component which will subscribe to platform event "Demo_Event__e" which we have created in our previous blog.

I have created an app page using lightning app builder named as "Platform Events App Page". and added this lightning component into it.

Code Snippet:

Below is snapshot of Lightning App page before platform event is fired.

Now fire platform event using workbench through REST API call

Platform event notification received in lightning component.

Hope this will help to understand platform events handling in lightning components. 

Looking forward for everyone's suggestions and comments!!!


Monday, April 22, 2019

Platform Events : Way to Deliver Custom Notifications within Salesforce or to external Applications

Salesforce provides Platform events which can be used create custom notification which can be used within Salesforce app or can be send to external applications. These notification are secure and scalable.

Platform events are part of Salesforce’s enterprise messaging platform. It utilizes publish and subscribe flow. One or many subscribe to same event and carry out different actions.

In lightning events, we define event and then create attributes through which information can shared between lightning components. Similar to this, you create platform event through point and click and then create custom fields which will be used to publish information by using platform events and subscriber can utilize this information.

Platform Events v/s Streaming API

  • In Streaming API (using Push Topics), subscriber receive notification based on changes or updates to records.
  • You can not edit or delete platform event records. You can only create or insert platform events.
  • Visualforce and Lightning component apps can subscribe to platform events using CometD similar to push topics.
  • You can not view platform event in Salesforce user interface and cannot query it through SOQL.
  • You can handle or subscribe platform events through triggers by using after insert.
  • Only "AfterInsert" event is available for platform event objects.
  • Platform events can be published by Process builder, Process Flow, apex, REST API by inserting an sObject.
  • Platform events persist for 24 hours only.
Permission for platform events is controlled through profile or permission sets.

Platform events can be used to publish information and has no dependency on existing salesforce records.

In order to create platform events, navigate to Setup --> Platform Events --> New Platform Event.

I have created a platform event "Demo Event" and going to use apex in order to publish event and subscribe this event through triggers.

When you create a platform event, the system appends the __e suffix to create the API name of the event.

How to fire/publish platform event
  • You have to create record in order to fire platform event.
To publish event messages, you create an instance of the event and pass it to the EventBus.publish method. Use below code snippet to publish event:

// Create an instance of the Demo event 
Demo_Event__e demoEvent = new Demo_Event__e(
           Event_Info__c='Demo event is fired using Apex', 
           Is_Event_Valid__c=true, 
           Event_Publisher__c='Apex Code');
// Call method to publish events
Database.SaveResult sr = EventBus.publish(demoEvent);
// Inspect publishing result 
if (sr.isSuccess()) {
    System.debug('Successfully published event.');
} else {
    for(Database.Error err : sr.getErrors()) {
        System.debug('Error returned: ' +
                     err.getStatusCode() +
                     ' - ' +
                     err.getMessage());
    }
}
  • You can create record using process builder or process flow.
  • You can create event using REST API. Below is details of HTTP Request:
Endpoint- /services/data/v45.0/sobjects/Demo_Event__e/
body
{
   "Event_Info__c" : "Demo event is fired using REST API CALL",
   "Is_Event_Valid__c" : true,
   "Event_Publisher__c" : "REST API CALL"
}
Method - POST
HTTP Response:

{   
   "id" : "e00xx0000000ccf",
   "success" : true,
   "errors" : [ ],
   "warnings" : [ ] 
}

How to Subscribe Platform Events using Apex Triggers

Whenever a record is created for platform event, after insert trigger gets fired. You can use below code to subscribe for platform event and perform logic as per your need:

trigger DemoEventTrigger  on Demo_Event__e (after insert) {
List<Task> taskList = new List<Task>();
for (Demo_Event__e event: Trigger.New) {
if (event.Is_Event_Valid__c == true) {
//perform logic based on event information
}
   }
}

Below is snapshot explaining Platform Events.
Hope this will help!!!