Sunday, 20 November 2022

Apex offers two ways to perform DML operations

Apex offers two ways to perform DML operations:


1. DML statements :


Eg : Insert Acc ;


This is more straightforward to use and result in exceptions that you can handle in your code.


2. Database class methods :


Eg: Database.insert(Acc, false);


By using the Database class method, you can specify whether or not to allow for partial record processing if errors are encountered. If you specify false for the second parameter and if a record fails, the remainder of DML operations can still succeed.


Instead of exceptions, a result object array (or one result object if only one sObject was passed in) is returned containing the status of each operation and any errors encountered.


So how do you choose between the two options available?


If you need the errors that occur during DML to be thrown as an Apex exception that immediately interrupts control flow --> then go for DML statements


If you need to allow partial success of DML. Using the Database class methods, you can write code that never throws DML exception errors. Instead, your code can use the appropriate results array to judge success or failure. --> then go for Database class methods


PS : Database methods also include a syntax that supports thrown exceptions, similar to DML statements.

Tuesday, 15 November 2022

New Salesforce Assert Class

 Using Assertion.Fail() to intentionally return a fatal error.

Using Assertion.isInstanceOfType() to assert object instance.


ex : 


try {

    Test.startTest();

    SomeClass.someMethod();

    System.Assert.Fail('Throw custom exception);

 } catch (Exception baseException) {

     System.Assert.isInstanceOfType(baseException, 

                                   SomeClass.SomeCustomException, 

                                   'Expected an instance of SomeCustomException');

 }

  

Using Assert.isNull() to assert the null values.


 ex :  

  Opportunity opp = OpportunityService.getRecentClosedOpportunity();

  System.Assert.isNotNull(opp, 'Expected the opportunity to not be null'); 

  System.Assert.isNull(calloutResponse, 'Expected a null response');


Using Assert.areEqual() instead of System.assertEquals() for clarity.


ex : 


Account acc = new Account();

acc.Name = 'Test Account';

insert acc;

System.Assert.areEqual('Test Account', acc.Name, 'Expected account name to be Test Account');


String sub = 'abcde'.substring(2);

System.Assert.areNotEqual('xyz', sub, 'Characters not expected after first two');


Using Assert.isTrue() instead of System.assert() for clarity.


ex:   

  

Boolean containsForce = 'Salesforce'.contains('force'); 

System.Assert.isTrue(containsForce, 'Expected true result.');

System.Assert.isFalse(containsForce,'Expected false result.');

System.Assert.isTrue(insertResults.isEmpty());


Note :


Write System.Assert.areEqual instead of Assert.areEqual and you can safely use the new classes.

Sunday, 13 November 2022

Upgrade Behavior Options of Unlocked Packages :

 Options when installing the unlocked packages.

1.Mixed Mode (Default behavior) :

Specifies that some removed components are deleted, and other components are marked deprecated.

2.Deprecate Only :

DeprecateOnly specifies that all removed components must be marked deprecated. 

The removed metadata exists in the target org after package upgrade, but is shown in the UI as deprecated from the package. 

This option is useful when migrating metadata from one package to another.


3.Delete :


Delete specifies to delete all removed components, except for custom objects

and custom fields, that don't have dependencies.

ex :

sfdx force:package:beta:install --package 04t... -t DeprecateOnly


Monday, 7 November 2022

Pre-requisites for creating Second-Generation Managed Packages

 1. Enable Dev Hub in your Org.

2. Enable Second-Generation Managed Packaging.

3. Install Salesforce CLI.

4. Create and Register Your Namespace


Note : Developers who work with 2GP packages need the correct permission set in the Dev Hub org.

       Developers need either the System Administrator Profile or the Create and Update Second-Generation Packages permission.

       

Namespace:


1.The namespace of a managed package is created in a namespace org and linked to the Dev Hub.

we can associate multiple namespaces to a single Dev Hub.

A namespace is linked with a 2GP when you run the force:package:create Salesforce CLI command And you must specify the namespace in the sfdx-project.json file.


2.Multiple packages can use the same namespace.


3.Multiple packages sharing the same namespace can share code using public 

Apex classes and methods @namespaceAccessible annotation.


 

How to register/link a namespace ?


Login to your Dev Hub org as the System Administrator or as a user with the Salesforce DX Namespace Registry Permissions.


Some of the orgs that you use with second-generation managed packaging have a unique purpose.


1.Choose your Dev Hub Org.

2.Namespace Org.

3.Other Orgs.



Purpose of Dev Hub :


As owner of all second-generation managed packages.

To link your Namespaces.

To authorize and run your force:package commands.

Note : Salesforce recommend that your Partner Business Org is also your DevHub Org.


Purpose of Namespace Org :


The primary purpose of the namespace org is to acquire a package namespace.

If you want to use the namespace strictly for testing,choose a disposable namespace.


After you create a namespace org and specify the namespace in it, open the Dev Hub org 

and link the namespace org to the Dev Hub org.


purpose of Other Orgs :


When you work with packages, you also use these orgs: you can ceate scratch orgs on the fly to use while testing your packages.

The target or installation org is where you install the package.

Behavior of Salesforce data in Apex tests

 1.Existing org data isn't visible to Apex tests.

2.As a best practice you should always create your own test data for each test.


Reasons to create your own test data :


1.Data unavailability

  your org might not have the data for both positive and negative tests.

2.Data inconsistency

  Data can be different between orgs and test runs.


Note : In some scenarios like testing report data or field history records 

        you might need to have access to our org data because you can't create 

         those records through apex.

       In those cases you can annotate your test class with 'seeAllData' is equal to true annotation.


  ex : @isTest(seeAllData=true)

       public class DemoCtrlTest{

          

          @isTest

          static void testAccountFilter(){

          

          }

       

       }  


3. Apex test data is transient and isn't committed to the database.


Note : which means the data is present only as long as your test is running.


4.Testsetup methods are helpful test setup methods are defined in a test class itself

   they take no arguments and no return a value.

   

   ex 

      @istest

      public class DemoCtrlTest{

      

      @testSetup 

       static void createTestData(){

         // create test data here

       }

      }


a. Test setup method is automatically executed first, before any test method.

b. Records created in the test setup method are accessible to all test methods.

c. Changes to records by a test method are rolled back before another test method is executed.

d. All records are rolled back after the test class finishes executing.


create test data using CSV file :


ex : @testSetup 

      static void creatTestData(){

        Test.loadData(Account.sobjectType,'Mock_Account_Data');

      }   


Test Data and Governor Limits :


Whenever a test class runs the test data creation and test execution both happens in the same transaction.   


ex : 

Test.startTest();

Test.stopTest();


The startTest() method marks the point in your test code where the test 

actually begins and stopTest() method marks the point where your test ends.


Any code that executes between these two methods is assigned a 'new set of governor limits '.

The code inside start and stop block has one set of limits and the code outside has another set of limits.

The code outside whether before or after that start and stop methods shares the same limit.


Wednesday, 26 October 2022

Deleting Salesforce Debug Logs

 Using SFDX:


COMMAND 1:


sfdx force:data:soql:query -q "SELECT Id FROM ApexLog" -r csv > apexlogs.csv


COMMAND 2:


sfdx force:data:bulk:delete -s ApexLog -f apexlogs.csv


Using Workbench:


Navigate to queries -> SOQL Query:


Select Bulk CSV and Input “Select id from ApexLog” to query Box then click Query.


Then download the CSV file by clicking on “download completed batch results” icon under Batches


Once you have the csv file: Navigate to data->delete. Then select from file, choose the downloaded file and click next.


Select Process records asynchronously via Bulk API and choose Object Type : ApexLog then click Confirm Delete. Done

How to add connected app in 2GP Managed Package?

 1.Create a connected App in Salesforce Instance where we maintain namespace.

2.Create a first-generation Managed package(1GP) and add the connected app.

it's fine if the connected app is the only component in the package.

Always use the same namespace as the 2GP package for the 1GP package.

3.Take note of the version number of the connected app,this number is needed later.

4.Upload the 1GP package to create a package version.

5.Promote the 1GP version to the released state.

6.Promoting the 1GP version allows the connected app to be included in a second-generation managed package.

we don't need to install the 1GP version into an org.

7.Now in our source code navigate to folder 'connectedApps' where we are trying to generate 2GP Package.


create an XML file with <connectedAppName>.connectedApp-meta.xml

and the body of the XML file should be as shown below.


<ConnectedApp xmlns="http://soap.sforce.com/2006/04/metadata">

    <developerName><namespace>__<connected_app_Name></developerName>

    <label>A Connected App</label>

    <version>1.0</version>

</ConnectedApp>


Now generate a 2GP package and promote. Then the connected app is automatically added to your 2GP Package.


The version specified in the source file is the version number of the connected app. Use decimal formatting when specifying the version number. 

The version number must match the version number of the connected app before it was added to the 1GP managed package.


Note:


When you add a connected app to a 1GP package and upload the package, the version number of the connected app is auto-incremented. 

For example, when version 1.0 of a connected app is added to a 1GP package, the package version increments the version number 

of the connected app from 1.0 to 2.0. When creating the source file for your 2GP package, specify the version number of the connected app 

before it was uploaded into a 1GP package, in this case, 1.0.


Reference:


https://developer.salesforce.com/docs/atlas.en-us.224.0.sfdx_dev.meta/sfdx_dev/sfdx_dev_dev2gp_connected_app.htm