Posts

Showing posts from December, 2020

Winter '21 Release Highlights - Programmatic Code

  Learn What’s New in Winter ‘21 Learning Objectives After completing this unit, you’ll be able to: Improve Apex testing with new SObject error methods. Develop flow screen components that work for multiple objects. Create custom property editors for Lightning web components. Enforce profile-based access for @AuraEnabled Apex classes. Make more powerful composite requests. Improve Apex Testing with New SObject Error Methods Track errors with the new  SObject.hasErrors()  and  SObject.getErrors()  methods without performing a DML operation to check the result for errors. Dynamically add errors to specific fields with new  SObject.addError()  overload methods. Use the  hasErrors()  method to know if an SObject instance contains errors. Use the  getErrors()  method to retrieve the list of errors for a specific SObject instance. If the  SObject.addError()  method has been called on an SObject instance, the  SObject.hasErr...

Get Hands-on With Field- and Object-Level Security and Safe Navigation Operator

Hands-on challenge solution for  Platform Developer I Certification Maintenance (Winter ‘21) @RestResource(urlMapping='/apexSecurityRest') global with sharing class ApexSecurityRest { @HttpGet global static Contact doGet() { Id recordId = RestContext.request.params.get('id'); Contact result; if (recordId == null) { throw new FunctionalException('Id parameter is required'); } //Refactored List<Contact> results = [SELECT id, Name, Title, Top_Secret__c, Account.Name FROM Contact WHERE Id = :recordId]; SObjectAccessDecision securityDecision = Security.stripInaccessible(AccessType.READABLE, results); if(!results.isEmpty()){ result = (Contact)securityDecision?.getRecords()[0]; result.Description = result?.Account?.Name; }else{ throw new SecurityException('You don\'t have access to all contact fields required to use this AP...

Using Aggregate SOQL queries/results in Batch Apex

I had created a schedulable batch apex that implements Database.Batchable<sObject> in Salesforce, but if you want to use SOQL having aggregate functions like SUM(), MAX(), COUNT() on results grouped by “GROUP BY” clause in start execution, changing to interface Database.Batchable<AggregateResult> isn’t a workable way, because it fails with the below compile error : Class must implement the global interface method: Iterable<AggregateResult> start(Database.BatchableContext) from Database.Batchable<AggregateResult> The following sample code will explain this. /* * Compile error : Class must implement the global interface method: Iterable<AggregateResult> start(Database.BatchableContext) from Database.Batchable<AggregateResult> */ global class SampleAggregateBatch implements Database.Batchable<AggregateResult> { // The batch job starts global Database.Querylocator start(Database.BatchableContext bc){ String query = 'SELECT COUNT(Id), ...