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.