Salesforce Notes
Salesforce Notes
Salesforce Notes
1. Fetch the child record from parent record (Contact is child and Account is Parent) –
Standard Objects
SELECT Id, Name, (SELECT Id, LastName FROM Contacts) FROM Account.
Note- Contacts is a Child Relationship Name which is lookup field in child object
2. Fetch the child record from parent record (Student__c is child and Teacher__c is
Parent) – Custom Objects
SELECT Id, Name, (SELECT Id, Name FROM Students__r) FROM Teacher__c
Note - Students is a Child Relationship Name(appended ‘ __r’ in Students) which is lookup field in
child object
3. Fetch the Parent record from Child Record (Contact is child and Account is Parent) –
Standard Object
4. Fetch the Parent record from Child Record (Student__c is child and Teacher__c is Parent) –
Custom Object
SELECT Id, Name FROM Account WHERE Id NOT IN (SELECT AccountId FROM Contact)
Nripesh Kumar Joshi (Salesforce Developer)
Note- We can not use count with the field that is used in Group By.
For example we can not count name because we are using Name field in Group By
8. Determine how many leads are associated with each LeadSource value
9. Fetch the Lead Record that are associate with each LeadSource that generated more
than 10 times
10. Fetch the Lead record where name end with ‘abc’
*** Group By - GROUP BY is used with Aggregate functions to group the result set by single or
multiple columns.
*** Having - HAVING is an optional clause that can be used in a SOQL query to filter results that
aggregate functions return.
*** WHERE - We can add the condition with the help of WHERE Clause
Ans : Suppose you want to fetch all fields of contact object then you can use
FIELDS(ALL).
FIELDS(ALL) – This fetches all the fields of an object. This is similar like Select * from
SQL.
If you try that in the developer console, though, you’ll get an “Unknown error parsing
query” message.
So, to execute the query, you need to open the anonymous code window from the
developer console.
Nripesh Kumar Joshi (Salesforce Developer)
system.debug('Deleted Account>>>>'+acc);
FOR UPDATE to lock sObject records while they’re being updated in order to prevent race
While an sObject record is locked, no other client or user is allowed to make updates either
through code or the Salesforce user interface. The client locking the records can perform
logic on the records and make updates with the guarantee that the locked records won’t be
This query returns all records that have the first name Nripesh and the last name kum.
SELECT Name FROM Contact WHERE FirstName = ‘Nripesh’ AND LastName= ‘Kum’
Nripesh Kumar Joshi (Salesforce Developer)
OR - Use OR to return records that meet one of two conditions. This query returns records
‘Kumar’
IN- Use IN to return records that meet at least one of three or more conditions. The IN
clause is commonly used to return the values of a picklist, or values from a LIST or SET.
This query returns all records that have the last name James, Barr, Nedaerk, or Forbes.
‘Nedaerk’, ‘Forbes’)
NULLS FIRST | LAST - Returns null records at the beginning (NULLS FIRST) or end
(NULLS LAST)
5. We want only accounts that have a related contact with the last name
Forbes ?
●
Use Apex triggers if performance and scale is important, if your
logic is too complex for the point-and-click tools.
●
Salesforce automatically fires active triggers when the specified
database events occur.
Nripesh
Trigger Syntax
●
A trigger definition starts with the trigger
keyword. It is then followed by the name of the
trigger, the Salesforce object that the trigger is
associated with, and the conditions under which
it fires.
Nripesh
Trigger Events
●
To execute a trigger before or after insert, update, delete, and
undelete operations, specify multiple trigger events in a comma-
separated list.The events you can specify are:
➔
before insert
➔
before update
➔
before delete
➔
after insert
➔
after update
➔
after delete
➔
after undelete
Nripesh
Types of Apex Trigger
●
There are two types of trigger.
Before trigger is used to update or After trigger is used to access the field
validate the record values before values that are set by the system such
save to the database as record id and to affect changes in
other record
Nripesh
Context Variables
●
To access the records that caused the trigger to fire.
isExecuting
●
Returns true if the current context for the Apex code is a trigger, not a Visualforce page, a Web service, or an
executeanonymous() API call.
isBefore
●
Returns true if this trigger was fired before any record was saved.
isAfter
●
Returns true if this trigger was fired after all records were saved.
isInsert
●
Returns true if this trigger was fired due to an insert operation, from the Salesforce user interface, Apex, or
the API.
isUpdate
●
Returns true if this trigger was fired due to an update operation, from the Salesforce user interface, Apex, or
the API.
isDelete
●
Returns true if this trigger was fired due to a delete operation, from the Salesforce user interface, Apex, or
the API.
Nripesh
Context Variables
isUndelete
●
Returns true if this trigger was fired after a record is recovered from the Recycle Bin (that is, after an
undelete operation from the Salesforce user interface, Apex, or the API.)
new
●
Returns a list of the new versions of the sObject records. Note that this sObject list is only available in
insert and update triggers, and the records can only be modified in before triggers.
newMap
●
A map of IDs to the new versions of the sObject records. Note that this map is only available in before
update, after insert, and after update triggers.
old
●
Returns a list of the old versions of the sObject records. Note that this sObject list is only available in
update and delete triggers.
oldMap
●
A map of IDs to the old versions of the sObject records. Note that this map is only available in update and
delete triggers.
size
●
The total number of records in a trigger invocation, both old and new.
Nripesh
How we can write apex Trigger ?
trigger ContextExampleTrigger on Account (before insert, after insert, after delete) {
if (Trigger.isInsert) {
if (Trigger.isBefore) {
// Process before insert
} else if (Trigger.isAfter) {
// Process after insert
}
}
else if (Trigger.isDelete) {
// Process after delete
}
}
Nripesh
●
If you create more than one trigger per object then you can not control
which trigger logic will execute first.So always use One trigger per object.
●
We should create a handler class and create a method inside that class
and then write logic there.
Nripesh
●
Instead of using the SOQL Query, we should be taking help from
Salesforce Collection and then reducing the error.
Nripesh
Example -->
trigger testTrigger on Acount__c(before insert) {
integer i = 1;
for (Acount__c acc: Trigger.new) {
acc.Address__c = 'Test Address ' + i;
i++;
}
}
Nripesh
Recursive Trigger
●
Recursion is the process of executing the same Trigger multiple
times to update the record again and again due to automation.
●
There is a way to avoid recursive trigger.
●
Use Static Boolean Variable.
●
This error is occured in below code
trigger TestTrigger on Test__c (before insert) {
insert new Test__c();
}
Nripesh
How to avoid Recursive Trigger ?
●
Create a class with a static Boolean variable with a default value
of true.
Nripesh
References
●
https://www.pantherschools.com/apex-trigger-best-practices-in-
salesforce/
●
https://jayakrishnasfdc.wordpress.com/2020/02/23/recursive-trig
ger-in-salesforce/
Thank You
Nripesh Kumar Joshi
s
should go with Batch class.
ie
ig
Batch class has three methods that are following.
od
1. Start Method
2. Execute Method
Pr
3. Finish Method
1. Start Method
ce
should be performed.
sf
2. Execute Method
This method processes a subset of the scoped records and performs
operations which we want to perform on the records fetched from the
start method.
s
ie
3. Finish Method
ig
This method executes after all batches are processed. This method is
od
used for any post job or wrap-up work like sending confirmation email
notifications.
Pr
Syntax of Finish Method —>
ce
}
sf
Example —>
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext BC, List<Account>
scope)
{
for(Account a : scope)
{
s
a.Name = a.Name + 'Updated';
ie
}
ig
update scope;
}
od
global void finish(Database.BatchableContext BC) {
}
Pr
}
ce
Database.Stateful Interface
or
For example, if your batch job is executing one logic and you need to
send an email at the end of the batch job with all successful records
le
and failed records. For that, you can use Database.Stateful in the
Sa
class definition.
s
Database.BatchableContext BC,
ie
List<sObject> scope){
ig
for(sObject s : scope){
Summary ++;
od
}
}
Pr
public void finish(Database.BatchableContext BC){
ce
}
}
or
sf
s
ie
1. By Declarative Approach →
ig
Step 1) Click on Setup->Apex class. Then search the Schedule Apex
od
button.
Pr
ce
or
sf
le
Sa
What is CRON?
CRON is a software utility that is a time-based job scheduler in
Unix-like computer operating systems. Developers who want to set up
and maintain software environments, use this CRON to schedule jobs
(commands or shell scripts) to run periodically at fixed times, dates, or
intervals.
s
ie
What is a CRON expression?
ig
A CRON expression is basically a string of five or six fields separated
by white spaces that represents a set of times, normally as a schedule
od
to execute some routine.
Pr
Use in Salesforce
Use schedule with an Apex class that implements the Schedulable
ce
job, an expression used to represent the time and date the job is
Sa
{5} Month - * indicates all values, i.e. every month. (if we only want to
run on 1st Jan say, this would be 1)
s
the week. We could also write this string as MON-FRI or preferably as
ie
* to indicate all values.
ig
So this job reads to run at "0 seconds past 0 minutes of the 5th hour
on no specific day of the month for every month of the year for every
od
day of the week".
The following are the values for the expression:
Pr
ce
or
sf
le
Sa
The special characters are defined as follows:
s
ie
ig
od
Pr
ce
or
sf
le
Sa
NOTE: Use the L and W together to specify the last weekday of the
month.
Cron Expression Examples
s
ie
ig
od
Pr
ce
or
sf
le
s
System.schedule(Schedule Job Name 6', '0 25 * * * ?', new
ie
testScheduleFiveMinutes());
ig
System.schedule(Schedule Job Name 7', '0 30 * * * ?', new
od
testScheduleFiveMinutes());
Pr
System.schedule(Schedule Job Name 8', '0 35 * * * ?', new
testScheduleFiveMinutes());
ce
testScheduleFiveMinutes());
sf
@isTest
public class AccountBatchTest {
static testMethod void testMethod1() {
List<Account> lstAccount= new List<Account>();
for(Integer i=0 ;i <200;i++) {
Account acc = new Account();
s
acc.Name ='Name'+i;
ie
lstLead.add(acc);
ig
}
insert lstAccount;
od
Test.startTest();
AccountBatch obj = new AccountBatch();
Pr
DataBase.executeBatch(obj);
Test.stopTest();
ce
}
}
or
sf
s
● Is Batch apex Stateless Or Stateful?
ie
● How to Implement Stateful in Batch class?
ig
● How can we schedule a batch class? How?
● Can we schedule Batch classes in Minutes or Hours? If yes,
od
How?
● Can we call one Batch class to another Batch class?
Pr
● Can we schedule a batch apex class with in that batch class?
● Can we call future method from a batch class?
ce
Development
Ans -- > Single sign-on (SSO) allows users to access multiple applications with a single set of
credentials. They do not need to remember separate user ID/password for each application.
Salesforce offers various options for configuring single sign-on. This also includes:
• Federated Authentication using SAML
• Delegated Authentication
• OpenID Connect
Ans -
REST API
REST API is a simple and powerful web service based on RESTful principles. It exposes all sorts of
Salesforce functionality via REST resources and HTTP methods. For example, you can create, read,
update, and delete (CRUD) records, search or query your data, retrieve object metadata, and access
information about limits in your org. REST API supports both XML and JSON.
Because REST API has a lightweight request and response framework and is easy to use, it’s great
for writing mobile and web apps.
SOAP API
SOAP API is a robust and powerful web service based on the industry-standard protocol of the
same name. It uses a Web Services Description Language (WSDL) file to rigorously define the
parameters for accessing data through the API. SOAP API supports XML only. Most of the SOAP
API functionality is also available through REST API. It just depends on which standard better
meets your needs.
Because SOAP API uses the WSDL file as a formal contract between the API and consumer, it’s
great for writing server-to-server integrations.
Bulk API
Bulk API is a specialized RESTful API for loading and querying lots of data at once. By lots, we
mean 50,000 records or more. Bulk API is asynchronous, meaning that you can submit a request
and come back later for the results. This approach is the preferred one when dealing with large
amounts of data. There are two versions of Bulk API (1.0 and 2.0). Both versions handle large
amounts of data, but we use Bulk API 2.0 in this module because it’s a bit easier to use.
Bulk API is great for performing tasks that involve lots of records, such as loading data into your
org for the first time.
Pub/Sub API
Use Pub/Sub API for integrating external systems with real-time events. You can subscribe to real-
time events that trigger when changes are made to your data or subscribe to custom events. The
APIs use a publish-subscribe, or pub/sub, model in which users can subscribe to channels that
broadcast data changes or custom notifications.
The pub/sub model reduces the number of API requests by eliminating the need for making frequent
API requests to get data. Pub/Sub API is great for writing apps that would otherwise need to
frequently poll for changes.
Pub/Sub API is built for high scale, bi-directional event integration with Salesforce. Use Pub/Sub
API to efficiently publish and subscribe to binary event messages in the Apache Avro format.
Pub/Sub API is based on gRPC and HTTP/2 and uses a pull-based model so you can control the
subscription flow. With Pub/Sub API, you can use one of the 11 programming languages that gRPC
supports.
Tooling API’s SOQL capabilities for many metadata types allow you to retrieve smaller pieces of
metadata. Smaller retrieves improve performance, making Tooling API a good fit for developing
interactive applications. Tooling API provides SOAP and REST interfaces.
When to Use GraphQL API
Build highly responsive and scalable apps by returning only the data a client needs, all in a single
request. GraphQL API overcomes the challenges posed by traditional REST APIs through field
selection, resource aggregation, and schema introspection. Field selection reduces the size of the
payload, sending back only fields that were included in the query. Aggregations reduce round trips
between the client and server, returning a set of related resources within a single response. Schema
introspection enables a user to see the types, fields, and objects that the user has access to.
Q. What is connected App in Salesforce and how can we create connected app in Salesforce ?
Ans - A connected app is a framework that enables an external application to integrate with
Salesforce using APIs and standard protocols, such as Security Assertion Markup Language
(SAML), OAuth, and OpenID Connect. Connected apps use these protocols to authorize,
authenticate, and provide single sign-on (SSO) for external apps.
6. In the "API (Enable OAuth Settings)" section, configure the OAuth settings:
• Callback URL : Provide the callback URL where your marketing automation tool
will redirect users after authentication. It should be a URL within your marketing
automation tool's settings.
• Selected OAuth Scopes : Choose the necessary OAuth scopes based on the
permissions your integration needs. For example, you might need "Access and
manage your data (api)" and "Perform requests on your behalf at any time
(refresh_token, offline_access)."
• Require Secret for Web Server Flow : If your integration will use the Web Server
OAuth flow, check this box.
7. Optionally, you can configure other settings, such as digital signatures or IP Relaxation
settings, depending on your security requirements.
9. After saving, Salesforce will generate a "Consumer Key" and "Consumer Secret." Keep
these values secure as they'll be used for authentication.
10.In the "Profiles" related list, specify which user profiles or permission sets are allowed to
use the connected app. Ensure that the appropriate users have access to the connected app.
11.In your custom marketing automation tool, implement OAuth 2.0 authentication using the
Salesforce connected app's Consumer Key and Secret. Follow Salesforce's OAuth 2.0
authentication flow to obtain access tokens.
12.Once you obtain an access token, use it to make authorized API requests to Salesforce. You
can create and update leads, contacts, and other Salesforce objects as needed from your
marketing automation tool.
13.Regularly monitor the integration's usage, and ensure that you handle token expiration and
token refresh logic in your integration to maintain seamless connectivity.
• Solution: Create a connected app in Salesforce and configure it to use the IdP's
authentication services, such as SAML or OpenID Connect, for user authentication and
single sign-on.
Scenario: Your company uses Salesforce for customer relationship management (CRM) and Google
Workspace (formerly G Suite) for email and collaboration. You want your Salesforce users to access
Google Workspace seamlessly without having to log in separately.
Solution: Create a connected app in Salesforce and configure it to use OAuth 2.0 for SSO with
Google Workspace. This way, users can log in to Salesforce and access Google Workspace
resources without additional login steps.
If you want to create a connected app in Salesforce first you search on Quick find box ‘App
Manager’ and select this after that you can click on New Connected App
https://trailhead.salesforce.com/content/learn/modules/mobile_sdk_introduction/
mobilesdk_intro_security
Q. Oauth Terminologies
OAuth (Open Authorization): OAuth is an open standard protocol that enables secure
authorization and authentication for granting access to resources, such as APIs, without exposing
user credentials.
Client Application: The software application that wants to access protected resources on behalf of
the user. In Salesforce integration, this could be a third-party app or system.
Resource Owner: The user or entity that owns the protected resource. In Salesforce, this is
typically a Salesforce user whose data or resources are being accessed.
Authorization Server: In Salesforce, the authorization server is the Salesforce Identity and Access
Management system. It handles user authentication and issues access tokens after the user grants
permission.
Access Token: An access token is a credential used by the client application to access protected
resources. In Salesforce, access tokens are short-lived and grant access to specific resources for a
limited time.
Refresh Token: A refresh token is a long-lived credential that can be used to obtain a new access
token when the current one expires. It is often used to maintain a long-term connection between the
client application and Salesforce.
Authorization Code: In the Web Server OAuth Authentication Flow, after the user is authenticated,
the authorization server issues an authorization code. This code is exchanged for an access token
and a refresh token by the client application.
Consumer Key: It is value used by the consumer—in this case, the Mobile SDK app—to identify
itself to Salesforce. Referred to as client_id.
Scopes: Scopes define the specific permissions and access rights requested by the client application.
In Salesforce, scopes can control the level of access to objects and data.
Redirect URI (Callback URL): When the user is authenticated and grants permissions, the
authorization server redirects the user's browser to a specific URL (the redirect URI) with the
authorization code. In Salesforce integrations, this URL is often provided by the client application.
JWT (JSON Web Token): JWT is a compact, URL-safe means of representing claims to be
transferred between two parties. In Salesforce, JWTs are used in the JWT Bearer Token OAuth
Authentication Flow for secure communication.
Connected App: In Salesforce, a connected app represents the client application that wants to
integrate with Salesforce using OAuth. Connected apps define various settings, including OAuth
settings, to control the integration.
User-Agent Flow: Also known as the Implicit Flow, this OAuth flow is used for single-page
applications and mobile apps where the access token is returned directly to the user's browser or
app.
Username-Password Flow: This OAuth flow allows the client application to directly exchange the
user's Salesforce credentials for an access token. It's generally discouraged due to security concerns.
Ans -> The Salesforce REST API lets you integrate with Salesforce applications using simple
HTTP methods, in either JSON or XML formats, making this an ideal API for developing mobile
applications or external clients.
Piece of code --> Retrieve the data from third party (Get the Data)
To test your POST callout, we provide an implementation of the HttpCalloutMock interface. This
interface enables you to specify the response that’s sent in the respond method. Your test class
instructs the Apex runtime to send this fake response by calling Test.setMock again. For the first
argument, pass HttpCalloutMock.class. For the second argument, pass a new instance of
AnimalsHttpCalloutMock, which is your interface implementation of HttpCalloutMock. (We’ll
write AnimalsHttpCalloutMock in the example after this one.)
Now add the class that implements the HttpCalloutMock interface to intercept the callout. If an
HTTP callout is invoked in test context, the callout is not made. Instead, you receive the mock
response that you specify in the respond method implementation in AnimalsHttpCalloutMock.
Apex Class
AnimalsCallouts
AnimalsCalloutsTest
@isTest
private class AnimalsCalloutsTest {
@isTest static void testGetCallout() {
// Create the mock response based on a static resource
StaticResourceCalloutMock mock = new StaticResourceCalloutMock();
mock.setStaticResource('GetAnimalResource');
mock.setStatusCode(200);
mock.setHeader('Content-Type', 'application/json;charset=UTF-8');
// Associate the callout with a mock response
Test.setMock(HttpCalloutMock.class, mock);
// Call method to test
HttpResponse result = AnimalsCallouts.makeGetCallout();
// Verify mock response is not null
System.assertNotEquals(null,result, 'The callout returned a null response.');
// Verify status code
System.assertEquals(200,result.getStatusCode(), 'The status code is not 200.');
// Verify content type
System.assertEquals('application/json;charset=UTF-8',
result.getHeader('Content-Type'),
'The content type value is not expected.');
// Verify the array contains 3 items
Map<String, Object> results = (Map<String, Object>)
JSON.deserializeUntyped(result.getBody());
List<Object> animals = (List<Object>) results.get('animals');
System.assertEquals(3, animals.size(), 'The array should only contain 3 items.');
}
}
HttpCalloutMock
@isTest
global class AnimalsHttpCalloutMock implements HttpCalloutMock {
// Implement this interface method
global HTTPResponse respond(HTTPRequest request) {
// Create a fake response
HttpResponse response = new HttpResponse();
response.setHeader('Content-Type', 'application/json');
response.setBody('{"animals": ["majestic badger", "fluffy bunny", "scary bear", "chicken",
"mighty moose"]}');
response.setStatusCode(200);
return response;
}
}
MyFirstRestAPIClass
@RestResource(urlMapping='/api/Account/*')
global with sharing class MyFirstRestAPIClass
{
@HttpGet
global static Account doGet() {
RestRequest req = RestContext.request;
RestResponse res = RestContext.response;
String AccNumber = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);
Account result = [SELECT Id, Name, Phone, Website FROM Account WHERE
AccountNumber = :AccNumber ];
return result;
}
@HttpDelete
global static void doDelete() {
RestRequest req = RestContext.request;
RestResponse res = RestContext.response;
String AccNumber = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);
Account result = [SELECT Id, Name, Phone, Website FROM Account WHERE
AccountNumber = :AccNumber ];
delete result;
}
@HttpPost
global static String doPost(String name,String phone,String AccountNumber ) {
Account acc = new Account();
acc.name= name;
acc.phone=phone;
acc.AccountNumber =AccountNumber ;
insert acc;
return acc.id;
}
MyFirstRestAPIClassTest
@IsTest
private class MyFirstRestAPIClassTest {
Step 3:- In the Workbench tool select Utilities > REST Explorer
Step 4:- In the REST Explorer window paste the following URL in the box
Method:- Get
URL:- /services/apexrest/api/Account/12345
Nripesh