You are on page 1of 7

private | public | global

[virtual | abstract | with sharing | without sharing]


class ClassName [implements InterfaceNameList] [extends ClassName]
{
// The body of the class
}

HelloWorld

public with sharing class HelloWorld {


public void printMessage() {
String msg = 'Hello World';
System.debug(msg);
}
}

sObject is just a Salesforce object.


In Apex, you can use enums with numbers, but you can’t define what these number values are.

If you tried to access the ordinal value of the third enum, the value of the enumOrd variable would
be 2.
Integer enumOrd = myEnums.Enum3.ordinal();
List
A list in an ordered collection of elements that works much the same as a traditional array. In fact,
arrays in Apex are synonymous with lists, and you can use them interchangeably. For example, the
following is one way to declare a variable as a list of strings.
List<String> myStrings = new List<String>();

public class AccountUtils {


public static List<Account> accountsByState (String accountState){
List<Account> searchedResults = [SELECT Name FROM Account WHERE
BillingState= :accountState];
return searchedResults;
}
}
SOSL
Find one term in one object
FIND {term} RETURNING ObjectTypeName
SOSL
Find one term in more objects
FIND {term} RETURNING ObjectTypeName1, ObjectTypeName2,
ObjectTypeNameYouGetTheIdea

SOQL
Single object search—SOQL works when you know which field the data resides in. Because we
didn’t specify the field for march 2016 email, a SOSL search is preferred over SOQL. In general, if
the query doesn’t specify a target field to search, SOSL works.
•Multiple object search—Because you can only retrieve data from multiple objects that are related
to one another, the multiple object search in SOQL is limited. In our scenario, the objects were
unrelated, so SOSL it is.
•Custom object search—As with a single object search, you could search through custom objects
in SOQL fine. However, we didn’t specify in which field the data resides for our search term pink
hi-top. In addition, SOQL searches against the database, not the index. So, let’s say that the record
actually included pink sneaker hi-top. SOQL wouldn’t be able to return the right results.
Future Method Syntax
global class SomeClass { @future public static void someFutureMethod(List<Id>
recordIds) { List<Account> accounts = [Select Id, Name from Account Where Id IN
:recordIds]; // process account records to do awesome stuff } }
Sample Callout Code

public class SMSUtils {


// Call async from triggers, etc, where callouts are not permitted.
@future(callout=true)
public static void sendSMSAsync(String fromNbr, String toNbr, String m) {
String results = sendSMS(fromNbr, toNbr, m);
System.debug(results);
}
// Call from controllers, etc, for immediate processing
public static String sendSMS(String fromNbr, String toNbr, String m) {
// Calling 'send' will result in a callout
String results = SmsMessage.send(fromNbr, toNbr, m);
insert new SMS_Log__c(to__c=toNbr, from__c=fromNbr, msg__c=results);
return results;
}
}

Test Classes

1st calls for 2nd

@isTest
global class SMSCalloutMock implements HttpCalloutMock {
global HttpResponse respond(HttpRequest req) {
// Create a fake response
HttpResponse res = new HttpResponse();
res.setHeader('Content-Type', 'application/json');
res.setBody('{"status":"success"}');
res.setStatusCode(200);
return res;
}
}
@IsTest
private class Test_SMSUtils {
@IsTest
private static void testSendSms() {
Test.setMock(HttpCalloutMock.class, new SMSCalloutMock());
Test.startTest();
SMSUtils.sendSMSAsync('111', '222', 'Greetings!');
Test.stopTest();
// runs callout and check results
List<SMS_Log__c> logs = [select msg__c from SMS_Log__c];
System.assertEquals(1, logs.size());
System.assertEquals('success', logs[0].msg__c);
}
}

Sample Batch Apex Code


public class UpdateContactAddresses implements
Database.Batchable<sObject>, Database.Stateful {
// instance member to retain state across transactions
public Integer recordsProcessed = 0;
public Database.QueryLocator start(Database.BatchableContext bc) {
return Database.getQueryLocator(
'SELECT ID, BillingStreet, BillingCity, BillingState, ' +
'BillingPostalCode, (SELECT ID, MailingStreet, MailingCity, ' +
'MailingState, MailingPostalCode FROM Contacts) FROM Account ' +
'Where BillingCountry = \'USA\''
);
}
public void execute(Database.BatchableContext bc, List<Account> scope){
// process each batch of records
List<Contact> contacts = new List<Contact>();
for (Account account : scope) {
for (Contact contact : account.contacts) {
contact.MailingStreet = account.BillingStreet;
contact.MailingCity = account.BillingCity;
contact.MailingState = account.BillingState;
contact.MailingPostalCode = account.BillingPostalCode;
// add contact to list to be updated
contacts.add(contact);
// increment the instance member counter
recordsProcessed = recordsProcessed + 1;
}
}
update contacts;
}
public void finish(Database.BatchableContext bc){
System.debug(recordsProcessed + ' records processed. Shazam!');
AsyncApexJob job = [SELECT Id, Status, NumberOfErrors,
JobItemsProcessed,
TotalJobItems, CreatedBy.Email
FROM AsyncApexJob
WHERE Id = :bc.getJobId()];
// call some utility to send email
EmailUtils.sendMessage(job, recordsProcessed);
}
}

Testing Batch Apex


@isTest
private class UpdateContactAddressesTest {
@testSetup
static void setup() {
List<Account> accounts = new List<Account>();
List<Contact> contacts = new List<Contact>();
// insert 10 accounts
for (Integer i=0;i<10;i++) {
accounts.add(new Account(name='Account '+i,
billingcity='New York', billingcountry='USA'));
}
insert accounts;
// find the account just inserted. add contact for each
for (Account account : [select id from account]) {
contacts.add(new Contact(firstname='first',
lastname='last', accountId=account.id));
}
insert contacts;
}
@isTest static void test() {
Test.startTest();
UpdateContactAddresses uca = new UpdateContactAddresses();
Id batchId = Database.executeBatch(uca);
Test.stopTest();
// after the testing stops, assert records were updated properly
System.assertEquals(10, [select count() from contact where MailingCity =
'New York']);
}
}

The start method provides the collection of all records that the execute method will process in
individual batches. It returns the list of records to be processed by calling
Database.getQueryLocator with a SOQL query. In this case we are simply querying for all Account
records with a Billing Country of ‘USA’.
•Each batch of 200 records is passed in the second parameter of the execute method. The execute
method sets each contact’s mailing address to the accounts’ billing address and increments
recordsProcessed to track the number of records processed.
•When the job is complete, the finish method performs a query on the AsyncApexJob object (a table
that lists information about batch jobs) to get the status of the job, the submitter’s email address,
and some other information. It then sends a notification email to the job submitter that includes the
job info and number of contacts updated.
The setup method inserts 10 account records with the billing city of ‘New York’ and the billing
country of ‘USA’. Then for each account, it creates an associated contact record. This data is used
by the batch class.
In the test method, the UpdateContactAddresses batch class is instantiated, invoked by calling
Database.executeBatch and passing it the instance of the batch class.
The call to Database.executeBatch is included within the Test.startTest and Test.stopTest block. This
is where all of the magic happens. The job executes after the call to Test.stopTest. Any
asynchronous code included within Test.startTest and Test.stopTest is executed synchronously after
Test.stopTest.
Finally, the test verifies that all contact records were updated correctly by checking that the number
of contact records with the billing city of ‘New York’ matches the number of records inserted
Queueable Syntax

public class SomeClass implements Queueable {


public void execute(QueueableContext context) {
// awesome code here
}
}

Sample Code
A common scenario is to take some set of sObject records, execute some processing such as making
a callout to an external REST endpoint or perform some calculations and then update them in the
database asynchronously. Since @future methods are limited to primitive data types (or arrays or
collections of primitives), queueable Apex is an ideal choice. The following code takes a collection
of Account records, sets the parentId for each record, and then updates the records in the database.

public class UpdateParentAccount implements Queueable {


private List<Account> accounts;
private ID parent;
public UpdateParentAccount(List<Account> records, ID id) {
this.accounts = records;
this.parent = id;
}
public void execute(QueueableContext context) {
for (Account account : accounts) {
account.parentId = parent;
// perform other processing or callout
}
update accounts;
}
}

To add this class as a job on the queue, execute the following code:

// find all accounts in ‘NY’


List<Account> accounts = [select id from account where billingstate = ‘NY’];
// find a specific parent account for all records
Id parentId = [select id from account where name = 'ACME Corp'][0].Id;
// instantiate a new instance of the Queueable class
UpdateParentAccount updateJob = new UpdateParentAccount(accounts, parentId);
// enqueue the job for processing
ID jobID = System.enqueueJob(updateJob);

You might also like