Thursday, July 20, 2017

Sales force interview questions: APEX

  1. By default all the variables and methods are non-static.
  2. Scope of the non-static variables or metods is within the scope of the same object.
  3. We can declare variables and methods as static by using static keyword.
  4. Scope of the static variables and methods is through out the transaction.
  5. Static variables and methods, we can directly call with class name (we cannot access static variables and methods with object name).

  1. List (ordered and allow duplicates)
  2. Set (unordered and won't allow duplicates)
  3. Map (Key and value pair)
ListSet
List is Ordered.Set is unordered.
List allows duplicates.Set doesn't allow duplicates.
We can access list elements with index.Set elements cannot be accessed with index.
We can sort list elements with sortmethod (default sorting order is ascending).sort method is not available for Set.
Contains method is not available in List.Contains method is available for Set to search for a particular element in the set.
We can process records which are stored in list using DML statements(insert, update, delete and undelete).We cannot process recordswhich are stored in set using DML statements.
No limit for the size of a list. It only depends on the heap size which is 6 MB (Synchronous) and 12 MB (Asynchronous).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//Map holds key and value pair.
//Syntax: Map<datatype,datatype> mapName = new Map<datatype,datatype>();
/*Map<string,string> countryISTCodeMap = new Map<string,string>();
countryISTCodeMap.put('India','91');
countryISTCodeMap.put('USA','001');
countryISTCodeMap.put('India','911');//replaces old value with new value.*/
Map<string,string> countryISTCodeMap = new Map<string,string>{'India'=>'91','USA'=>'001', 'India'=>'911'};
 
system.debug('countryISTCodeMap result: '+countryISTCodeMap+' with size '+countryISTCodeMap.size());
system.debug('countryISTCodeMap keys: '+countryISTCodeMap.keyset());
system.debug('countryISTCodeMap values: '+countryISTCodeMap.values());
system.debug('countryISTCodeMap search: '+countryISTCodeMap.containsKey('India'));
system.debug('countryISTCodeMap fetching value based on key: '+countryISTCodeMap.get('India'));
//map keys are case-sensitive.
</string,string></string,string></string,string></string,string></datatype,datatype></datatype,datatype>
  1. keyset(): To fetch only keys from the map.
  2. values(): To fetch only values from the map.
  3. containsKey(value): To search a key from the map.
  4. get(key): By supplying the key we can fetch the value.
  5. put(key,value): To add key and value in a map.

  1. Insert
  2. Update
  3. Delete
  4. Undelete
  5. Upsert (Combination of insert and update)
  6. Merge (Combination of update and delete)
  1. Number of DML statements per transaction: 150 (as a whole including insert, update, delete and undelete)
  2. Number of rows processed per DML stmt: 10000
  1. SOQL: Salesforce Object Query Language
  2. SOQL Purpose: To fetch info. from an object and related objects.
  3. We can write query on one object while querying on those objects we can fetch the child object info. or parent object info. (we cannot capture un related objects info.)
  4. SOQL queries per transaction: 100.
  5. SOQL query rows returned: 50000.
  1. SOSL: Salesforce Object Search Language
  2. SOSL Purpose:We can search for a value in multiple objects (no need of any relationship).
  3. Results of SOSL query can be stored in List of List.
  4. SOSL queries per transaction: 20.
  5. SOSL query rows returned: 2000.
insert/updateDatabase.insert/Database.update
Assume that you are inserting 100 records. If any one of the record fail due to error then entire operation will fail. None of the records will be saved into the database.Assume that you are inserting 100 records. If any one of the record fail due to error then it will perform partial operation (valid records will be inserted/updated) if we use Database.insert(list,false)/ Database.update(list,false).
with insert/update if we use try-catch then we can capture only one error which will cause to stop the operation.with Database.insert/Database.update we can capture all the errors by saving result in Database.saveResult[].
Queues will store in Group object. To query for MyQueue from the database using SOQL, we should use the following syntax -
?
1
Group grp = [select Id, Name from Group where Name = 'MyQueue' and Type = 'Queue' Limit 1];
 List oppLst = [select id, name , amount from Opportunity where amount != null order by amount desc limit 10];
   

Before Mode: Before the record is saving into the database, it will fire.
After Mode: After the record is saved into the database (doesn't commit at this point of time), it will fire.
BeforeAfter
before insertafter insert
before updateafter update
before deleteafter delete
-after undelete
Note: before undelete event is not available.
To capture the runtime information we use trigger context variables.
Below context variables will return either true or false.
  1. Trigger.isBefore (returns true if the trigger context is Before Mode)
  2. Trigger.isAfter (returns true if the trigger context is After Mode)
  3. Trigger.isInsert (returns true if the trigger context is Insert)
  4. Trigger.isUpdate (returns true if the trigger context is Update)
  5. Trigger.isDelete (returns true if the trigger context is Delete)
  6. Trigger.isUndelete (returns true if the trigger context is Undelete)
  7. Trigger.isExecuting (returns true if the apex class method is getting call from Apex Trigger)
Below context variables will store records at runtime.
  1. trigger.old (stores history (old versions) of the records.)
  2. trigger.oldMap (stores history (old versions) of the records along with id.)
  3. trigger.new (stores new version of the records.)
  4. trigger.newMap (stores new version of the records along with id.)
Apex Trigger Collections availability for the different events -
Eventstrigger.oldtrigger.oldMaptrigger.newtrigger.newMap
before insert
after insert
before update
after update
before delete
after delete
after undelete
Read/Write access over the trigger collections on different events -
Eventstrigger.oldtrigger.oldMaptrigger.newtrigger.newMap
before insertNANARead/WriteNA
after insertNANARead OnlyRead Only
before updateRead OnlyRead OnlyRead/WriteRead Only
after updateRead OnlyRead OnlyRead OnlyRead Only
before deleteRead OnlyRead OnlyRead OnlyRead Only
after deleteRead OnlyRead OnlyRead OnlyRead Only
after undeleteRead OnlyRead OnlyRead OnlyRead Only
Before Triggers
  1. To perform the validations we should use before triggers.
  2. If you are updating any field on the same object on which you are writing the trigger and no need to explicitly include the DML statemetns (already due to DML operation only trigger fire and it is still in progress at this point of time.)
After Triggers
  1. If you are dealing with relationship records and if you need record id in these situations we should use after trigger (in before insert record doesn't contain the record id).
We cannot control the order of execution in this situation. It is recommended to have only one trigger per one object.
Note: We can keep the logic of the apex trigger in an apex class and can invoke from that class.
If we perform update operation on the record in after update event logic recursive triggers will arise.
Using static boolean variable in an apex class (we should not keep static boolean variable inside of the trigger) we can avoid recursive triggers.
If we perform DML operation on standard/custom object and global objects(User, UserRole, Group, GroupMember, Permission Set, etc...) in same transaction this error will come.
To avoid this error, we should perform DML operation on standard/custom object records in a different transaction.
In general all the apex classes and apex triggers execute synchronously (execute immediately).
if we perform DML operation on standard/custom object records asynchronously (execute in future context), we can avoid MIXED-DML-OPERATION error.
To execute logic asynchronously keep the logic in an apex method (in a separate apex class, not in same apex trigger) which is decorated with @future annotation.
see the below example -
Note: To analyse the code copy it and paste it in notepad for the convenience.
public class TriggerUtility {
 /*
 1. Following future method execute asynchronously (whenever server is free it will execute in future context).
 2. We should not declare @future method in Apex Trigger.
 3. @future method should be always static.
 4. @future method accepts only primitive data types (Integer, String, Boolean, Date, etc...) as parameters and it won't accept
 non-primitive data types (sObject,Custom Objects and standard Objects etc.. ) as parameters.
 5. @future method should not contain return type. Always it should be void.
 6. From an apex trigger we can make only make asynchronous call outs. To make call out we should include "callout = true" beside the future @annotation.
 7. We cannot perform synchronous call outs from Apex Trigger.
 */
 //Below is the example for the future method -
 @future(callout = true)
 public static void processAsync(primitive parameters) {
  //Logic to insert/update the standard/custom object.
 }
}
?

Relationship between ChildObject__c and ParentObject__c objects is Lookup relationship.
In case of lookup relationship if we delete the parent object record in child object only the relationship field value will be removed (child records won't be deleted).
But client has a requirement to delete the child object records. How to achieve this?

Write an apex trigger to achieve this functionality.
We should take before delete event. If we take after delete relationship will broke up b/w parent and child object records.
?
1
2
3
4
5
6
7
8
9
10
Trigger ParentTrigger on ParentObject__c(before delete) {
 /*
 Note:
 - For delete events only trigger.old and triggger.oldMap will be available.
 - trigger.old holds old versions of the records but if we mention that in SOQL query salesforce will automatically convert those records into ids.
 */
 List<childobject__c> childLst = [select id, Parent_Object__c from ChildObject__c where Parent_Object__c in: trigger.old];  
 delete childLst;
}
 </childobject__c>
We are creating validation rules, workflow rules, assignment rules, auto-responsive rules, escalation ruels and apex triggers etc..
If the condition is same for all the rules which will execute first and which will execute next, for this salesforce provide the order.
Order of execution in salesforce - Order of execution in Salesforce:
  1. Prepare the record for insert/update operation.
  2. It will replace all the old field values with new field values.
  3. If the request is coming form UI all the system validations will execute -
    • DataType
    • Length
    • Required
    • unique
    • pageLayot level validations
  4. before triggers
  5. Custom Validations and again system validation rules will fire (pageLayot level validations won't fire at this point of time).
  6. record will be saved into the database but doesn't not commit.
  7. after triggers.
  8. assignment rules.
  9. auto-responsive rules.
  10. Workflow Rules
  11. incase of Workflow Rule Field updates again before triggers and after triggers fire one more time. System validation ruels for duplicate chcek.
  12. Escalatoin Rules.
  13. Rollup-Summary fields will be calculated.
  14. Grant parent Rollup-Summary fields will be calculated.
  15. Criteria base sharing evaluation.
  16. Record will be commited into the database.
  17. Post Commit logic (Sending emails).
Validation rules will fire first then workflow rules will fire. So, the answer is 100 (Even though there is a validation rule because of the workflow rule it will accept 100 in the amount field).
It will throw the validation error because after the workflow field update before triggers fire one more time.

We can call the apex code by creating object for the class (or) if the variables or methods are static then we can call with class name.
Apex Code in the trigger will execute automatically for the DML operations.

If you want to execute apex code on a specific time then we should write batch class.
  • With Batch Apex we can process maximum of 50 million records.
  • Batch Apex is asynchronous (execute in future context).
  • While writing the batch class we should inherit Database.Batchable interface.
  • Database is a built in global class which contains inner global interface.
Since we are inheriting Database.Batchable interface we should implement all the method prototypes declared in the interface.
We should implement the following global methods -
  1. start: It will prepare the records to process and execute only one time.
  2. execute: It will take the records prepared in start method and split those records into batches and it will execute multiple times. For example if the start method is returning 1000 records then execute method executes 5 times if you don't mention the batch size (Default Batch Size is: 200). Maximum batch size is: 2000.
  3. finish: We can perform post commit logic like sending emails with the success or error information. It will execute only one time.
Batch Class Syntax:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//Database is Class provided by Salesforce.
//Batchable is an global interface which is inside of the Database class.
//Batchable include 3 method prototypes: 1. start 2. execute 3. finish
//start and finish methods will execute only one time.
//execute method executes multiple times.
global class BatchUsage implements Database.Batchable <sobject>, Database.Stateful {
 //at a time we can inherit multiple interfaces but we cannot inherit multiple classes.
 //By default batch class is stateless (variable info. store in one method cannot be remembered in other method),
 //to make it stateful we should inherit Database.Stateful interface.
 String name = '';
 global Database.queryLocator start(Database.BatchableContext bc) {
   
  //From asynchronous to asynchronous we cannot call
  //(from batch class we cannot call future mehthod vice versa.).
  name += 'start';
  system.debug('@@@Start Method: '+name);
  //Collects the records to process. It will forward these records to execute method.
  //If we use Iterable<sobject> as return type for this start method it can hold
  //max. of 50k records only.
  //If we use Database.queryLocator as return type for this start method it can hold
  //max. of 50 million records.
  return Database.getQueryLocator('select id, name, Location__c from Department__c where Location__c = \'\'');
 }
 global void execute(Database.BatchableContext bc, LIST<sobject> sObjLst) {
  name += 'execute';
  system.debug('@@@Execute Method: '+name);
  //Split the records forwarded by start method into batches.
  //Default batch size is: 200.
  //Max. batch size is: 2000.
  List<department__c> depUPdLst = new List<department__c>();
  for(SObject sObj: sObjLst) {
   Department__c dept = (Department__c) sObj;//Type Casting.
   dept.Location__c = 'Bangalore';
   depUPdLst.add(dept);
  }
  if(depUPdLst.size() > 0)
   update depUPdLst;
 }
 global void finish(Database.BatchableContext bc) {
  name += 'finish';
  system.debug('@@@Finish Method: '+name);
  //Post Commit logic like sending emails for the success or failures of the batches.
  AsyncApexJob a = [select id, Status, NumberOfErrors, JobItemsProcessed,
  TotalJobItems, CreatedBy.Email from AsyncApexJob where id =: bc.getJobId()];
   
  Messaging.singleEmailMessage mail = new Messaging.singleEmailMessage();
  mail.setToAddresses(new String[]{a.CreatedBy.Email});
  mail.setSubject('Batch Class Result');
  mail.setHtmlBody('The batch Apex job processed ' + '<b>' + a.TotalJobItems + '</b>' +
  ' batches with '+ '<b>' + a.NumberOfErrors + '</b>' + ' failures.');
  //sendEmail methods
  Messaging.sendEmail(new Messaging.singleEmailMessage[]{mail});
   
  /*** Scheduling in minutes or hours ***/
  /*//Create object for schedulable class
  SchedulableUsage su = new SchedulableUsage();
  //Preparing chron_exp
  Datetime sysTime = System.now();
  sysTime = sysTime.addminutes(6);
  String chron_exp = '' + sysTime.second() + ' ' + sysTime.minute() + ' ' +
  sysTime.hour() + ' ' + sysTime.day() + ' ' + sysTime.month() + ' ? ' + sysTime.year();           
  System.schedule('Dep Update'+sysTime.getTime(),chron_exp, su);*/
 }
}
 </department__c></department__c></sobject></sobject></s
To schedule the batch class we should write a separate class by implementing Schedulable interface.
After writing the above mentioned class to schedule navigate to: Develop> Apex Classes> Schedule Apex.
By clicking on Schedule Apex button we can schedule the batch class through user interface.
Note: Through user interface we cannot schedule in hours/minutes.
Schedulable Class Syntax:
?
1
2
3
4
5
6
7
   global class SchedulableUsage implements Schedulable {
 global void execute(SchedulableContext sc) {
  BatchUsage bu = new BatchUsage();
  //Database.executeBatch(bu);//Default Batch Size is: 200.
  Database.executeBatch(bu,1500);//Max. Batch Size is: 2000.
 }
}
To schedule the batch class in minutes/hours, in the finish method we should use System.schedule method which will take 3 parameters Job Name, Chrone Expression and schedulable class instance name respectively.
?
1
2
3
4
5
6
7
8
9
    /*** Scheduling in minutes or hours ***/
//Create object for schedulable class
SchedulableUsage su = new SchedulableUsage();
//Preparing chron_exp
Datetime sysTime = System.now();
sysTime = sysTime.addminutes(6);
String chron_exp = '' + sysTime.second() + ' ' + sysTime.minute() + ' ' +
sysTime.hour() + ' ' + sysTime.day() + ' ' + sysTime.month() + ' ? ' + sysTime.year();           
System.schedule('Dep Update'+sysTime.getTime(),chron_exp, su);
By default batch class is stateless (variable value which is stored in one method cannot be remembered in another method).
To maintain the state for the batch class, we should inherit Database.Stateful interface.

Scenario: In a set list of emails are stored in execute method. In the finish method that set is not having any emails. What is the reason?
Answer: By default batch class is stateless. Emails which are added to set can be remembered only in execute method. If we try to access the set in finish method you won't see those emails. In finish method if you want to access those emails of that set we should inherit the interface called Database.Stateful.
Yes it is possible, starting with Apex saved using Salesforce API version 26.0, you can call Database.executeBatch or System.scheduleBatch from the finish method. This enables you to start or schedule a new batch job when the current batch job finishes.
For previous versions, you can’t call Database.executeBatch or System.scheduleBatch from any batch Apex method. Note that the version used is the version of the running batch class that starts or schedules another batch job. If the finish method in the running batch class calls a method in a helper class to start the batch job, the Salesforce API version of the helper class doesn’t matter.
We cannot call one asynchronous process from another asynchronous process.
Since @future method and Batch Class both are asynchronous we cannot call future method from batch class or we cannot call batch class from the future method.
To cover the code for the batch class we should call the batch class from the inside of the Test.startTest() and Test.stopTest().
?
1
2
3
Test.startTest();
 //Call the batch class from here.
Test.stopTest();
Up to 5 batch jobs can be queued or active.
By implementing Database.Batchable and Schedulable interfaces we can implement the methods in a same class.
Though it is possible it is not recommended to write like this.

After developing an apex class or apex trigger we should write the unit tests and ensure that we are able to execute at least 75% of the lines of code.
If you are moving the code from sandbox to sandbox regarding code coverage you won't face any issue.
If you are moving the code from sandbox to production, you need to include all the test classes at the time of deployment and salesforce will run all the test classes which you included for the deployment as well as test classes which are already present in production, if the code coverage is less than 75% deployment will fail.
we cannot write test code (test methods) inside of the apex trigger.
From API Version 28.0, we cannot write the test methods inside of an apex class which is not decorated with @isTest.
We can write test methods only in a class which is decorated with @isTest.
Note: We have a governor limit for the overall Apex Code size of the organization which is of 3 MB. If we decorate a class with @isTest annotation Apex Code Size governor limit will be bypassed.
1
2
3
4
5
6
7
8
9
10
@isTest
 private class MyTestClass {
 
static testMethod void myTest1() {
}
 
static testMethod void myTest2() {
}
 
 }
Note: Test Class can be either public or private.
By default test class cannot recognize the existing data in the database.
if you mention @isTest(seeAllData = true) then test class can recognize the existing data in the database.
See the below examples -
  • From a List Custom Settings we cannot fetch the existing data without seeAllData = true in test class.
  • Suppose you have a custom object called 'CustomObject__c' and it contains many records, we cannot fetch the existing data without seeAllData = true in test class.
Note: It is not recommended to use seeAllData = true for a test class. Based on the existing data in database code coverage will impact.
Test.startTest() and Test.stopTest() maintains fresh set of governor limits. Assume that you are consuming 99 SOQL queries outside of Test.startTest() and Test.stopTest() then if you include any SOQL inside of Test.startTest() and Test.stopTest() count will start from 1.
Per testMethod we can use Test.startTest() and Test.stopTest() only for one time.
To execute asynchronous methods synchronously we can call those methods from inside of Test.startTest() and Test.stopTest().

Test.startTest() and Test.stopTest() are very useful when your test class hits Salesforce Governor Limits.

The code inside Test.startTest() and Test.stopTest() have new set of Salesforce Governor Limits. As a good practice, make sure initializing the variables, fetching records, creating and updating records are coded before Test.startTest() and Test.stopTest() and calling the controllers for code coverage is done inside Test.startTest() and Test.stopTest(). The code before Test.startTest() and after Test.stopTest() have new set of Salesforce Governor Limits and code between Test.startTest() and Test.stopTest() have new set of Salesforce Governor Limits.

Sample Test Class:

private class TestClass {
        static testMethod void test() {
                /*
                        Declare the variables, Fetch the required records, Create and update sample records
                */
                /*
                        Test.startTest();
                        /*
                        Call the controller for code coverage
                        */
                        Test.stopTest();
                */
        }
}
By default test class runs in System Mode. If you want to execute a piece of code in a certain user context then we can use system.runAs(UserInstance). For more details refer 2nd question in visualforce category.
To avoid MIXED-DML-OPERATION error we can include DML statements inside of system.runAs(), still the error persists keep DML statements inside of Test.startTest() and Test.stopTest().
What is the purpose?
To compare Actual value and Expected value we use assert statements.
Types of assert statements
  1. system.assertEquals(val1,val2): If both val1 and val2 are same then test class run successfully otherwise test class will fail.
  2. system.assertNotEquals(val1,val2): If both val1 and val2 are not same then test class run successfully otherwise test class will fail.
  3. system.assertEquals(val1> val2): If the condition satisfied then test class run successfully otherwise test class will fail.
Sometimes we cannot satisfy certain if conditions for the apex classes, in those situations on those if conditions we can add Test.isRunningTestseparated with or condition. Example: if(condition || Test.isRunningTest())
Sometimes in test classes we need to access a variable from Apex Class, if it is private we cannot access for that we will replace private with public. for this reason we are compromising the security. To avoid this before the private variables in apex class we can include @TestVisible so that even though variable is private we can access from the test class.
  1. We should not depend on the existing data in the database. We should create the test data for all the possible scenarios. Note: Profiles and recordTypes cannot be created programmatically, we can query from the database. For the remaining objects including users we should create the test data.
  2. While testing apex triggers and batch classes, we should do bulk testing at least with 200 records.
  3. We should test for all the positive and negative scenarios.

Following are the different types of web services -
  1. SOAP API -
    • SOAP: Simple Object Access Protocol
    • API: Application Programming Interface
    • SOAP API web services are available from long term.
    • SOAP protocol is used for the communication between the platforms.
    • Information exchange will happen with 'WSDL'.
    • WSDL: Web service Description Language
    • Default data exchange format is XML (used to exchange data in webservices)
  2. REST API -
    • REST: Representational State Transfer
    • REST API web services are available from last 10 years. Now a days most of the implementations are happening with REST API
    • Http protocol/SOAP protocol is used for the communication between the platforms(mostly http protocols will be used).
    • No concept of 'WSDL' in REST API. Information will be appended to endpoint URL
    • Default data exchange format is JSONXML format also can be used.
    • JSON: JavaScript Object Notation
    • JSON is light weight and easy to parse the data when compared with XML.

No comments:

Post a Comment