Force.com Apex Basics 
Sujit Kumar 
Zenolocity LLC © 2012 - 2024
Apex Overview 
• Basics – comparison to Java 
• Types, Casting, Rounding, Date, Time, DateTime 
• Arrays and Collections 
• Exceptions 
• Future Methods 
• Database Integration – SOQL, SOSL, DML, Database 
Methods, Triggers, Security. 
• OO – Classes, Interfaces, Inheritance, Polymorphism 
• Debug Logs – Categories & Levels, Filters 
• Unit Testing
Apex Language Basics 
• OO, Stored Procedure like language, runs on 
Force.com platform only. 
• Tightly integrated with Force.com DB. 
• Used to code user interfaces and triggers. 
• Apex programs run in a multi-tenant 
environment => subject to governor limits. 
• Integrated testing – code coverage atleast 75% 
to be deployed to prod.
Declarative Patterns 
• Simplicity & Speed 
• Data Model – Objects, Fields & Relationships 
• Business Logic – Workflow, Validation Rules & 
Assignment Rules 
• User Interface – Applications, Tabs, Page 
Layouts & Record Types
Programmatic Patterns via Apex 
• Control & Flexibility 
• Data Model – Metadata Web Services API. 
• Business Logic – VF Controllers, Apex, Web 
Services API. 
• User Interface – Visualforce Pages, Web 
Controls.
Overview (contd…) 
• Platform automatically upgraded. Force.com will 
run all your tests before upgrade. 
• No offline runtime environment for Apex 
programs, must be deployed to Force.com for 
execution. 
• Only supported language on Force.com platform. 
• Force.com DB is the only DB integrated into Apex. 
• 2 choices for development – Web Based App 
Builder Tool and Force.com IDE (standalone or 
eclipse plug-in).
Apex .vs. Java 
• Very similar – strongly typed, pass by 
reference, Object Oriented, etc. 
• Differences include: 
• Apex runs in a multi-tenant environment 
• Subject to limits 
• Case-insensitive 
• Transactional behavior is out of the box.
Apex Types 
• Strongly Typed language, similar to Java. 
• String (contains Unicode characters), Boolean, 
DateTime, Date, Time, Integer (signed 32-bit), 
Long (signed 64-bit), Decimal (signed m.n, 
total of 19 characters), Double (signed 64-bit 
with decimal), Blob, ID, Object. 
• ID stores the unique ID of DB records. Total of 
18 characters. Values checked at compile time 
& run time. Can throw StringException.
sObject Data Type 
• Represents a row in the Force.com database. 
• Initialized to null by default. Null data type 
contains the null constant. 
• Declared using the API name for the object. 
• Can be instantiated using name/value pairs. 
• sObject reference field key can be used to 
insert, update or upsert to resolve foreign keys 
by external ID.
Casting 
• Implicit conversion for Numeric Types. 
• Integer => Long => Double => Decimal 
• ID and String are interchangeable, can throw 
StringException. 
• Convert from string to numeric types using 
valueOf method. Can throw TypeException. 
Examples: Integer.valueOf(‘123’), 
Decimal.valueOf(‘123.34’)
Rounding 
• By default, the rounding mode is HALF_EVEN, 
which rounds to the nearest neighbor, or to 
the even neighbor if equidistant. 
• Examples: 0.5 will round to 0, 0.6 will round to 
1, 1.5 will round to 2.
Date, DateTime, Time 
• Use valueOf method on Date and DateTime. 
• No valueOf method on Time type. 
• For Date, default format is YYYY-MM-DD 
• For Datetime: YYYY-MM-DD HH:MM:SS 
• DateTime has a format method that follows 
the SimpleDateFormat of java.
Arrays and Collections 
• Collections: List, Set and Map. 
• Collections support 4 methods: clear, clone, 
isEmpty and size. 
• Multi-dimensional arrays are NOT supported. 
• 2-D list object by nesting a list within a list is 
possible. 
• Arrays and Lists are interchangeable. (See 
Speaker Notes)
Collections 
• Not more than 1000 elements in a collection. 
• A Collection can contain another collection - not more 
than 5 levels deep. 
• Cannot add/remove while iterating over a collection. 
• Set - unordered collection of unique primitives. 
• List - ordered collection of primitives, sObjects, 
collections or Apex objects based on indices. 
• Map - collection of unique primitive keys, values can be 
primitives, sObjects, collections or Apex objects.
Exceptions 
• Similar to Java using try, catch and finally. 
• Common system exceptions: 
DmlException (issues with changes to the DB), 
NullPointerException, 
QueryException (issues with DB queries), and 
TypeException (issues converting data types). 
• System Exception during recursion – max stack 
depth is not documented.
Apex Asynchronous Execution 
• Asynchronous mode of execution using Future 
methods. 
• Future methods tagged with @future. 
• Used to perform expensive tasks that are not 
time-critical. 
• A regular synchronous method can begin some 
work and invoke a future method to finish it. 
• The future method starts fresh with respect to 
governor limits (3MB code, 200k l.o.c., 50k 
records retrieved from SOQL).
Limitations of Future Methods 
• Cannot invoke more than 10 future methods in a single 
scope of execution. 
• FMs cannot call other FMs. 
• Signature is always static and void. 
• Parameters have to primitive types or collections of 
primitive types. 
• Cannot test FMs like normal methods (NMs). 
• Max of 200 FMs per user within a 24-hour window. 
• How to test FMs? Invoke a NM as the only line in a FM and 
write test cases for the NM that is invoked in the FM. 
• Batch Apex is more powerful than FMs.
Database Integration in Apex 
• Database integrated into the language & runtime. 
• No ORM tools, no DB connection pools. 
• Apex code aware of all objects, fields and security 
rules. 
• All DB Objects (standard and custom) are 
implicitly imported as Classes in Apex. 
• Use SOQL to retrieve. 
• Built-in DML to do CRUD operations.
DB Integration (contd…) 
• Can write apex code in triggers. 
• Apex code runs in a privileged mode, granting full 
access to all data. Can be configured to run as a 
certain user. 
• References to database objects and fields are 
verified at compile time. 
• Database relationships are also exposed in Apex. 
The __r syntax refers to a relationship field, a 
field that contains a reference to another object 
or list of objects.
SOQL Basics 
• Centered on a single DB object, specifying 1 or more fields 
to retrieve from it. 
• Case-insensitive. 
• The result of a SOQL query can be a simple list of records 
containing rows and columns or hierarchies of records 
containing data from multiple, related objects. 
• Child-to-Parent SOQL – simple list of child objects. Where 
fields from a parent object are included in the query, they 
are available as nested variables in Apex code. 
• Parent-to-Child SOQL – simple list of parent objects. Each 
record of the parent object includes a nested List of child 
objects.
SOQL For Loop 
• Allows it to run when the Project object contains up to 
50,000 records for this year without consuming 50,000 
records worth of heap space at one time. 
Decimal totalHours = 0; 
for (Proj__c project : [ SELECT Total_Billable_Hours_Invoiced__c 
FROM Proj__c 
WHERE Start_Date__c = THIS_YEAR ]) { 
totalHours += project.Total_Billable_Hours_Invoiced__c; 
} 
• Above code is still inefficient & run out of governor limits. 
• Change the type of variable in the For loop to a list of 
Project records, Force.com provides up to 200 records per 
loop iteration. This allows you to modify a whole list of 
records in a single operation.
DML 
• 5 Statements supported – up to 200 records of he 
same type. 
1. Insert 
2. Update (records identified by Id field) 
3. Upsert: try update first, otherwise insert. 
4. Delete: moves records to Recycle Bin. 
5. Undelete: restores records from Recycle Bin. 
• Can use DML statements (all or nothing when 
there is error) or database methods (allow partial 
success).
Triggers – when to use them. 
• A validation rule is required that is too complex to 
define on the database object using formula 
expressions. 
• Two objects must be kept synchronized. When a 
record in one object is updated, a trigger updates 
the corresponding record in the other. 
• Records of an object must be augmented with 
values from another object, a complex calculation 
or external data via a Web service call.
Triggers 
• Work on insert, update, delete and undelete. 
• Work with both COs and SOs. 
• Before Triggers - update validate values before 
saving. 
• After Triggers - have access to field values 
automatically set like ID or lastUpdated. 
• No before undelete event. 
• Triggers can be set to active or inactive. 
• Specified order of events when a trigger 
executes.
Trigger Considerations 
• All triggers are bulk triggers & can process 
multiple records at a time. 
• All triggers run as System by default. Override it 
by using "with sharing" keywords. 
• Triggers cannot contain the static keyword 
• Triggers can only contain keywords applicable to 
an inner class. 
• addError method prevents DML events from 
taking action on particular records.
Implicit Variables in Triggers 
• Trigger.new, Trigger.newMap, Trigger.old, 
Trigger.oldMap, isInsert, isUpdate, isExecuting, … 
• Trigger.newMap and Trigger.oldMap map IDs to 
sObjects. 
• Trigger.new is a collection. When used as a bind 
variable in a SOQL query, Apex transforms the records 
into corresponding ids. 
Example: 
Contact[] cons = [SELECT LastName FROM Contact 
WHERE AccountId IN :Trigger.new];
Trigger example 
trigger validateTimecard on Timecard__c 
( 
before insert, 
before update 
) 
{ 
// Apex code block 
}
Batch Processing in Triggers 
• Always try to bulkify a trigger. 
• Bulkifying a trigger – is the process of hardening a trigger 
to accept a batch of records. 
• triggers can always be invoked with a list of records and 
should be optimized accordingly. 
• Batches can be up to 200 records. 
• Example: 
List<Resource__c> toInsert = new List<Resource__c>(); 
for (Contact contact : contacts) { 
toInsert.add(new Resource__c( 
Name = contact.FirstName + ' ' + contact.LastName)); 
} 
insert toInsert;
Error Handling in Triggers 
• Strings describing validation errors can be 
added to individual records or fields using the 
addError method. Force.com continues to 
process the batch, collecting any additional 
errors, and then rolls back the transaction and 
returns the errors to the initiator of the 
transaction. 
• All changes are rolled back when there is an 
uncaught exception.
Database Security in Apex 
• Apex always runs in a privileged, system 
context that gives it access to read and write 
all data. 
• Where full access is not appropriate, Apex 
provides the with sharing keyword.
OO Features 
• Quite similar to Java. 
• Automatic properties: properties with no 
code body. When no code body is present, the 
getter and setter logic is implied. 
• Example: 
public Integer cost { get; set; } 
• Access modifiers on automatic properties: 
public Integer readOnly { get; private set; } 
public Integer writeOnly { private get; set; }
Access Modifiers 
• Classes: public (visible to the app namespace) 
and global (visible to all app namespaces) 
• If an inner class is global, its outer class is 
required to be global. 
• Methods and Properties: private, protected 
(class and sub-classes), public and global. 
• If a method is global, its class must be global as 
well. 
• If no access modifier is provided, the method or 
variable is private.
Polymorphism 
• The parent class must specify the virtual or 
abstract keywords on the methods to be 
overridden. 
• In the subclass, the override keyword is used 
on the virtual or abstract methods to declare 
that they’re replacing implementations in the 
parent class.
Debug Log 
• Cannot step through the code & set breakpoints. 
• A debug log records database operations, system processes, and errors that occur 
when executing a transaction or while running unit tests. 
• The system generates a debug log for a user every time that user executes a 
transaction that is included in the filter criteria. 
• You can retain and manage the debug logs for specific users. 
• Each entry written to the log is assigned a debug log category and level. 
• Debug log categories: Database, Apex Code, Apex Profiling, Callout, System, 
Validation, Visualforce, Workflow. 
• Debug log levels: Error, Warn, Info, Debug, Fine, Finer and Finest. (EWIDFFF) 
• To view saved debug logs, click Your Name | Setup | Monitoring | Debug Logs.
Limits of Debug Logs 
• Once a user is added, that user can record up to 20 
debug logs. After a user reaches this limit, debug logs 
stop being recorded for that user. Click Reset on the 
Monitoring Debug logs page to reset the number of 
logs for that user back to 20. Any existing logs are not 
overwritten. 
• Each debug log can only be 2 MB. Debug logs that are 
larger than 2 MB in size are truncated. 
• Each organization can retain up to 50 MB of debug 
logs. Once your organization has reached 50 MB of 
debug logs, the oldest debug logs start being 
overwritten.
Debug Log Execution & Code Units 
• An execution unit is equivalent to a transaction. It 
contains everything that occurred within the 
transaction. The execution is delimited 
by EXECUTION_STARTED and 
EXECUTION_FINISHED. 
• Code Unit is a discrete unit of work within a 
transaction. Units of code are indicated 
by CODE_UNIT_STARTED and CODE_UNIT_FINISH 
ED. Units of work can embed other units of work.
Debug Log Example 
EXECUTION_STARTED 
CODE_UNIT_STARTED|[EXTERNAL]execute_anonymous_apex 
CODE_UNIT_STARTED|[EXTERNAL]MyTrigger on Account trigger event 
BeforeInsert for [new] 
CODE_UNIT_FINISHED <-- The trigger ends 
CODE_UNIT_FINISHED <-- The executeAnonymous ends 
EXECUTION_FINISHED
Debug Log Line 
• Log lines are made up of a set of fields, delimited by a pipe (|). 
The format is: 
• timestamp: consists of the time when the event occurred and a 
value between parentheses. The time is in the user's time zone and 
in the format HH:mm:ss.SSS. 
• event identifier: consists of the specific event that triggered the 
debug log being written to, such 
as SAVEPOINT_RESET or VALIDATION_RULE, and any additional 
information logged with that event, such as the method name or 
the line and character number where the code was executed. 
• Example: 
11:47:46.038 (38450000)|USER_DEBUG|[2]|DEBUG|Hello World!
Debug Log Levels – Execution Path and 
Overrides 
• When you override the debug log levels for a 
class or trigger, these debug levels also apply 
to the class methods that your class or trigger 
calls and the triggers that get executed as a 
result. 
• All class methods and triggers in the execution 
path inherit the debug log settings from their 
caller, unless they have these settings 
overridden.
View Logs 
• In the Force.com IDE, a user interface is provided 
for the debug log on the right side of the Execute 
Anonymous and Test Runner views. It displays 
debug log entries resulting from code executed 
by these views. 
• Each has a text area for the log entries, a drop-down 
list of debug log categories, and a slider for 
adjusting the log level. 
• Each category receives its own independent log 
level, although only one can be shown at a time 
in the user interface.
Unit Testing 
• Test Coverage = 100 x (l.o.c. executed during test runs / 
total l.o.c.). Expressed as a percentage. The loc is from 
triggers and classes. 
• Test Methods – static void methods in an outer class 
with the testMethod keyword added. 
• Designate a class with the @isTest annotation to treat 
all it’s methods as test methods. Classes annotated 
with isTest must be declared as private. 
• Tests subjected to same governor limits as Apex code. 
• Each test method is independently subject to governor 
limits and not cumulative with other test methods in a 
class.
Unit Testing (contd…) 
• A test is successful if it executes without encountering 
an uncaught exception. 
• System.assert( boolean expression ). If the boolean 
expression is false, a System.Exception is thrown and 
the test fails. 
• All database modifications occurring during execution 
of a test method are rolled back after the method is 
completed. 
• Best practices: create own test data in a setup phase 
before tests are executed and limit assertions to that 
test data. Create environment agnostic test case data.
Testing Governor Limits 
• Test governor limits using system static 
methods provided by Apex - Test.startTest and 
Test.stopTest. 
• Useful when working with large data sets. 
• These static methods allow a test method to 
separate the Apex resources and governor 
limits being used to prepare and initialize the 
dataset from the resources and limits used 
during the actual test execution.
Test.start & Test.stop Methods 
• Test.startTest - marks the point in your test code when your test 
actually begins. Each test method is allowed to call this method 
only once. 
• All of the code before this method should be used to initialize 
variables, populate data structures, and so on, allowing you to set 
up everything you need in order to run your test. 
• After you call this method, you get a fresh set of governor limits for 
the remainder of the test until you call Test.stopTest. 
• Use Test.stop method in conjunction with the startTest method. 
Each test method is allowed to call this method only once. After 
calling this method, any post assertions are done in the original 
context.
System.runAs(user) { …} 
• Generally, all Apex code runs in system mode, and the 
permissions and record sharing of the current user are 
not taken into account. 
• System.runAs() lets you write test methods that change 
user contexts to either an existing user or a new user. 
All of that user's record sharing is then enforced. 
• System.runAs() can only be used in a test method. 
• The original system context is started again after all 
runAs() test methods complete. 
• System.runAs() will test and verify proper data sharing 
and data access but does not validate CRUD or Field 
Level Security permissions.
Strategies to test Controllers 
• Directly invoke controller getters/setters and 
action methods. 
• Setup constructor code to read URL 
arguments to establish controller state or 
perform actions. 
• Verify data in the database using SOQL and 
SOSL queries. 
• Use System.runAs blocks to simulate different 
users; System.runAs(user) {block; }.
Testing Visualforce Custom Controllers 
& Controller Extensions 
Example: 
public static testMethod void testMyController() { 
PageReference pageRef = Page.success; 
Test.setCurrentPage(pageRef); 
MyController controller = new MyController(); 
String nextPage = controller.save().getUrl(); 
System.assertEquals('/apex/failure?error=noParam', nextPage); 
ApexPages.currentPage().getParameters().put('qp', 'yyyy'); 
controller = new MyController(); 
controller.setLastName('lastname'); 
controller.setFirstName('firstname'); 
nextPage = controller.save().getUrl(); 
System.assertEquals('/apex/success', nextPage); 
}
Testing Triggers 
• Best Practice for trigger development: Keep 
the trigger’s code block as small as possible. 
• Place code in a separate class for easier 
maintenance and to encourage code reuse.
Running Tests 
• There are 2 primary ways to execute test methods: 
• Salesforce UI 
1. Via the Apex Test Execution Page 
2. Via the list of classes under Setup > Develop > Apex 
Classes 
3. Via a specific class under Setup > Develop > Apex 
Classes > Class Name 
• Metadata API 
1. via Force.com IDE 
2. runTests() method in the SOAP API
Testing – Best Practices 
• Strive for 100% code coverage instead of the 75% 
requirement. 
• Write portable tests that do not rely on data 
specific to an environment or org. 
• Should not commit to DB nor send emails. 
• Use the runAs method to test with different user 
contexts. 
• Test methods should execute Apex code with 
large data sets. Running tests in bulk mode will 
test the governor limits of your code.

SFDC Introduction to Apex

  • 1.
    Force.com Apex Basics Sujit Kumar Zenolocity LLC © 2012 - 2024
  • 2.
    Apex Overview •Basics – comparison to Java • Types, Casting, Rounding, Date, Time, DateTime • Arrays and Collections • Exceptions • Future Methods • Database Integration – SOQL, SOSL, DML, Database Methods, Triggers, Security. • OO – Classes, Interfaces, Inheritance, Polymorphism • Debug Logs – Categories & Levels, Filters • Unit Testing
  • 3.
    Apex Language Basics • OO, Stored Procedure like language, runs on Force.com platform only. • Tightly integrated with Force.com DB. • Used to code user interfaces and triggers. • Apex programs run in a multi-tenant environment => subject to governor limits. • Integrated testing – code coverage atleast 75% to be deployed to prod.
  • 4.
    Declarative Patterns •Simplicity & Speed • Data Model – Objects, Fields & Relationships • Business Logic – Workflow, Validation Rules & Assignment Rules • User Interface – Applications, Tabs, Page Layouts & Record Types
  • 5.
    Programmatic Patterns viaApex • Control & Flexibility • Data Model – Metadata Web Services API. • Business Logic – VF Controllers, Apex, Web Services API. • User Interface – Visualforce Pages, Web Controls.
  • 6.
    Overview (contd…) •Platform automatically upgraded. Force.com will run all your tests before upgrade. • No offline runtime environment for Apex programs, must be deployed to Force.com for execution. • Only supported language on Force.com platform. • Force.com DB is the only DB integrated into Apex. • 2 choices for development – Web Based App Builder Tool and Force.com IDE (standalone or eclipse plug-in).
  • 7.
    Apex .vs. Java • Very similar – strongly typed, pass by reference, Object Oriented, etc. • Differences include: • Apex runs in a multi-tenant environment • Subject to limits • Case-insensitive • Transactional behavior is out of the box.
  • 8.
    Apex Types •Strongly Typed language, similar to Java. • String (contains Unicode characters), Boolean, DateTime, Date, Time, Integer (signed 32-bit), Long (signed 64-bit), Decimal (signed m.n, total of 19 characters), Double (signed 64-bit with decimal), Blob, ID, Object. • ID stores the unique ID of DB records. Total of 18 characters. Values checked at compile time & run time. Can throw StringException.
  • 9.
    sObject Data Type • Represents a row in the Force.com database. • Initialized to null by default. Null data type contains the null constant. • Declared using the API name for the object. • Can be instantiated using name/value pairs. • sObject reference field key can be used to insert, update or upsert to resolve foreign keys by external ID.
  • 10.
    Casting • Implicitconversion for Numeric Types. • Integer => Long => Double => Decimal • ID and String are interchangeable, can throw StringException. • Convert from string to numeric types using valueOf method. Can throw TypeException. Examples: Integer.valueOf(‘123’), Decimal.valueOf(‘123.34’)
  • 11.
    Rounding • Bydefault, the rounding mode is HALF_EVEN, which rounds to the nearest neighbor, or to the even neighbor if equidistant. • Examples: 0.5 will round to 0, 0.6 will round to 1, 1.5 will round to 2.
  • 12.
    Date, DateTime, Time • Use valueOf method on Date and DateTime. • No valueOf method on Time type. • For Date, default format is YYYY-MM-DD • For Datetime: YYYY-MM-DD HH:MM:SS • DateTime has a format method that follows the SimpleDateFormat of java.
  • 13.
    Arrays and Collections • Collections: List, Set and Map. • Collections support 4 methods: clear, clone, isEmpty and size. • Multi-dimensional arrays are NOT supported. • 2-D list object by nesting a list within a list is possible. • Arrays and Lists are interchangeable. (See Speaker Notes)
  • 14.
    Collections • Notmore than 1000 elements in a collection. • A Collection can contain another collection - not more than 5 levels deep. • Cannot add/remove while iterating over a collection. • Set - unordered collection of unique primitives. • List - ordered collection of primitives, sObjects, collections or Apex objects based on indices. • Map - collection of unique primitive keys, values can be primitives, sObjects, collections or Apex objects.
  • 15.
    Exceptions • Similarto Java using try, catch and finally. • Common system exceptions: DmlException (issues with changes to the DB), NullPointerException, QueryException (issues with DB queries), and TypeException (issues converting data types). • System Exception during recursion – max stack depth is not documented.
  • 16.
    Apex Asynchronous Execution • Asynchronous mode of execution using Future methods. • Future methods tagged with @future. • Used to perform expensive tasks that are not time-critical. • A regular synchronous method can begin some work and invoke a future method to finish it. • The future method starts fresh with respect to governor limits (3MB code, 200k l.o.c., 50k records retrieved from SOQL).
  • 17.
    Limitations of FutureMethods • Cannot invoke more than 10 future methods in a single scope of execution. • FMs cannot call other FMs. • Signature is always static and void. • Parameters have to primitive types or collections of primitive types. • Cannot test FMs like normal methods (NMs). • Max of 200 FMs per user within a 24-hour window. • How to test FMs? Invoke a NM as the only line in a FM and write test cases for the NM that is invoked in the FM. • Batch Apex is more powerful than FMs.
  • 18.
    Database Integration inApex • Database integrated into the language & runtime. • No ORM tools, no DB connection pools. • Apex code aware of all objects, fields and security rules. • All DB Objects (standard and custom) are implicitly imported as Classes in Apex. • Use SOQL to retrieve. • Built-in DML to do CRUD operations.
  • 19.
    DB Integration (contd…) • Can write apex code in triggers. • Apex code runs in a privileged mode, granting full access to all data. Can be configured to run as a certain user. • References to database objects and fields are verified at compile time. • Database relationships are also exposed in Apex. The __r syntax refers to a relationship field, a field that contains a reference to another object or list of objects.
  • 20.
    SOQL Basics •Centered on a single DB object, specifying 1 or more fields to retrieve from it. • Case-insensitive. • The result of a SOQL query can be a simple list of records containing rows and columns or hierarchies of records containing data from multiple, related objects. • Child-to-Parent SOQL – simple list of child objects. Where fields from a parent object are included in the query, they are available as nested variables in Apex code. • Parent-to-Child SOQL – simple list of parent objects. Each record of the parent object includes a nested List of child objects.
  • 21.
    SOQL For Loop • Allows it to run when the Project object contains up to 50,000 records for this year without consuming 50,000 records worth of heap space at one time. Decimal totalHours = 0; for (Proj__c project : [ SELECT Total_Billable_Hours_Invoiced__c FROM Proj__c WHERE Start_Date__c = THIS_YEAR ]) { totalHours += project.Total_Billable_Hours_Invoiced__c; } • Above code is still inefficient & run out of governor limits. • Change the type of variable in the For loop to a list of Project records, Force.com provides up to 200 records per loop iteration. This allows you to modify a whole list of records in a single operation.
  • 22.
    DML • 5Statements supported – up to 200 records of he same type. 1. Insert 2. Update (records identified by Id field) 3. Upsert: try update first, otherwise insert. 4. Delete: moves records to Recycle Bin. 5. Undelete: restores records from Recycle Bin. • Can use DML statements (all or nothing when there is error) or database methods (allow partial success).
  • 23.
    Triggers – whento use them. • A validation rule is required that is too complex to define on the database object using formula expressions. • Two objects must be kept synchronized. When a record in one object is updated, a trigger updates the corresponding record in the other. • Records of an object must be augmented with values from another object, a complex calculation or external data via a Web service call.
  • 24.
    Triggers • Workon insert, update, delete and undelete. • Work with both COs and SOs. • Before Triggers - update validate values before saving. • After Triggers - have access to field values automatically set like ID or lastUpdated. • No before undelete event. • Triggers can be set to active or inactive. • Specified order of events when a trigger executes.
  • 25.
    Trigger Considerations •All triggers are bulk triggers & can process multiple records at a time. • All triggers run as System by default. Override it by using "with sharing" keywords. • Triggers cannot contain the static keyword • Triggers can only contain keywords applicable to an inner class. • addError method prevents DML events from taking action on particular records.
  • 26.
    Implicit Variables inTriggers • Trigger.new, Trigger.newMap, Trigger.old, Trigger.oldMap, isInsert, isUpdate, isExecuting, … • Trigger.newMap and Trigger.oldMap map IDs to sObjects. • Trigger.new is a collection. When used as a bind variable in a SOQL query, Apex transforms the records into corresponding ids. Example: Contact[] cons = [SELECT LastName FROM Contact WHERE AccountId IN :Trigger.new];
  • 27.
    Trigger example triggervalidateTimecard on Timecard__c ( before insert, before update ) { // Apex code block }
  • 28.
    Batch Processing inTriggers • Always try to bulkify a trigger. • Bulkifying a trigger – is the process of hardening a trigger to accept a batch of records. • triggers can always be invoked with a list of records and should be optimized accordingly. • Batches can be up to 200 records. • Example: List<Resource__c> toInsert = new List<Resource__c>(); for (Contact contact : contacts) { toInsert.add(new Resource__c( Name = contact.FirstName + ' ' + contact.LastName)); } insert toInsert;
  • 29.
    Error Handling inTriggers • Strings describing validation errors can be added to individual records or fields using the addError method. Force.com continues to process the batch, collecting any additional errors, and then rolls back the transaction and returns the errors to the initiator of the transaction. • All changes are rolled back when there is an uncaught exception.
  • 30.
    Database Security inApex • Apex always runs in a privileged, system context that gives it access to read and write all data. • Where full access is not appropriate, Apex provides the with sharing keyword.
  • 31.
    OO Features •Quite similar to Java. • Automatic properties: properties with no code body. When no code body is present, the getter and setter logic is implied. • Example: public Integer cost { get; set; } • Access modifiers on automatic properties: public Integer readOnly { get; private set; } public Integer writeOnly { private get; set; }
  • 32.
    Access Modifiers •Classes: public (visible to the app namespace) and global (visible to all app namespaces) • If an inner class is global, its outer class is required to be global. • Methods and Properties: private, protected (class and sub-classes), public and global. • If a method is global, its class must be global as well. • If no access modifier is provided, the method or variable is private.
  • 33.
    Polymorphism • Theparent class must specify the virtual or abstract keywords on the methods to be overridden. • In the subclass, the override keyword is used on the virtual or abstract methods to declare that they’re replacing implementations in the parent class.
  • 34.
    Debug Log •Cannot step through the code & set breakpoints. • A debug log records database operations, system processes, and errors that occur when executing a transaction or while running unit tests. • The system generates a debug log for a user every time that user executes a transaction that is included in the filter criteria. • You can retain and manage the debug logs for specific users. • Each entry written to the log is assigned a debug log category and level. • Debug log categories: Database, Apex Code, Apex Profiling, Callout, System, Validation, Visualforce, Workflow. • Debug log levels: Error, Warn, Info, Debug, Fine, Finer and Finest. (EWIDFFF) • To view saved debug logs, click Your Name | Setup | Monitoring | Debug Logs.
  • 35.
    Limits of DebugLogs • Once a user is added, that user can record up to 20 debug logs. After a user reaches this limit, debug logs stop being recorded for that user. Click Reset on the Monitoring Debug logs page to reset the number of logs for that user back to 20. Any existing logs are not overwritten. • Each debug log can only be 2 MB. Debug logs that are larger than 2 MB in size are truncated. • Each organization can retain up to 50 MB of debug logs. Once your organization has reached 50 MB of debug logs, the oldest debug logs start being overwritten.
  • 36.
    Debug Log Execution& Code Units • An execution unit is equivalent to a transaction. It contains everything that occurred within the transaction. The execution is delimited by EXECUTION_STARTED and EXECUTION_FINISHED. • Code Unit is a discrete unit of work within a transaction. Units of code are indicated by CODE_UNIT_STARTED and CODE_UNIT_FINISH ED. Units of work can embed other units of work.
  • 37.
    Debug Log Example EXECUTION_STARTED CODE_UNIT_STARTED|[EXTERNAL]execute_anonymous_apex CODE_UNIT_STARTED|[EXTERNAL]MyTrigger on Account trigger event BeforeInsert for [new] CODE_UNIT_FINISHED <-- The trigger ends CODE_UNIT_FINISHED <-- The executeAnonymous ends EXECUTION_FINISHED
  • 38.
    Debug Log Line • Log lines are made up of a set of fields, delimited by a pipe (|). The format is: • timestamp: consists of the time when the event occurred and a value between parentheses. The time is in the user's time zone and in the format HH:mm:ss.SSS. • event identifier: consists of the specific event that triggered the debug log being written to, such as SAVEPOINT_RESET or VALIDATION_RULE, and any additional information logged with that event, such as the method name or the line and character number where the code was executed. • Example: 11:47:46.038 (38450000)|USER_DEBUG|[2]|DEBUG|Hello World!
  • 39.
    Debug Log Levels– Execution Path and Overrides • When you override the debug log levels for a class or trigger, these debug levels also apply to the class methods that your class or trigger calls and the triggers that get executed as a result. • All class methods and triggers in the execution path inherit the debug log settings from their caller, unless they have these settings overridden.
  • 40.
    View Logs •In the Force.com IDE, a user interface is provided for the debug log on the right side of the Execute Anonymous and Test Runner views. It displays debug log entries resulting from code executed by these views. • Each has a text area for the log entries, a drop-down list of debug log categories, and a slider for adjusting the log level. • Each category receives its own independent log level, although only one can be shown at a time in the user interface.
  • 41.
    Unit Testing •Test Coverage = 100 x (l.o.c. executed during test runs / total l.o.c.). Expressed as a percentage. The loc is from triggers and classes. • Test Methods – static void methods in an outer class with the testMethod keyword added. • Designate a class with the @isTest annotation to treat all it’s methods as test methods. Classes annotated with isTest must be declared as private. • Tests subjected to same governor limits as Apex code. • Each test method is independently subject to governor limits and not cumulative with other test methods in a class.
  • 42.
    Unit Testing (contd…) • A test is successful if it executes without encountering an uncaught exception. • System.assert( boolean expression ). If the boolean expression is false, a System.Exception is thrown and the test fails. • All database modifications occurring during execution of a test method are rolled back after the method is completed. • Best practices: create own test data in a setup phase before tests are executed and limit assertions to that test data. Create environment agnostic test case data.
  • 43.
    Testing Governor Limits • Test governor limits using system static methods provided by Apex - Test.startTest and Test.stopTest. • Useful when working with large data sets. • These static methods allow a test method to separate the Apex resources and governor limits being used to prepare and initialize the dataset from the resources and limits used during the actual test execution.
  • 44.
    Test.start & Test.stopMethods • Test.startTest - marks the point in your test code when your test actually begins. Each test method is allowed to call this method only once. • All of the code before this method should be used to initialize variables, populate data structures, and so on, allowing you to set up everything you need in order to run your test. • After you call this method, you get a fresh set of governor limits for the remainder of the test until you call Test.stopTest. • Use Test.stop method in conjunction with the startTest method. Each test method is allowed to call this method only once. After calling this method, any post assertions are done in the original context.
  • 45.
    System.runAs(user) { …} • Generally, all Apex code runs in system mode, and the permissions and record sharing of the current user are not taken into account. • System.runAs() lets you write test methods that change user contexts to either an existing user or a new user. All of that user's record sharing is then enforced. • System.runAs() can only be used in a test method. • The original system context is started again after all runAs() test methods complete. • System.runAs() will test and verify proper data sharing and data access but does not validate CRUD or Field Level Security permissions.
  • 46.
    Strategies to testControllers • Directly invoke controller getters/setters and action methods. • Setup constructor code to read URL arguments to establish controller state or perform actions. • Verify data in the database using SOQL and SOSL queries. • Use System.runAs blocks to simulate different users; System.runAs(user) {block; }.
  • 47.
    Testing Visualforce CustomControllers & Controller Extensions Example: public static testMethod void testMyController() { PageReference pageRef = Page.success; Test.setCurrentPage(pageRef); MyController controller = new MyController(); String nextPage = controller.save().getUrl(); System.assertEquals('/apex/failure?error=noParam', nextPage); ApexPages.currentPage().getParameters().put('qp', 'yyyy'); controller = new MyController(); controller.setLastName('lastname'); controller.setFirstName('firstname'); nextPage = controller.save().getUrl(); System.assertEquals('/apex/success', nextPage); }
  • 48.
    Testing Triggers •Best Practice for trigger development: Keep the trigger’s code block as small as possible. • Place code in a separate class for easier maintenance and to encourage code reuse.
  • 49.
    Running Tests •There are 2 primary ways to execute test methods: • Salesforce UI 1. Via the Apex Test Execution Page 2. Via the list of classes under Setup > Develop > Apex Classes 3. Via a specific class under Setup > Develop > Apex Classes > Class Name • Metadata API 1. via Force.com IDE 2. runTests() method in the SOAP API
  • 50.
    Testing – BestPractices • Strive for 100% code coverage instead of the 75% requirement. • Write portable tests that do not rely on data specific to an environment or org. • Should not commit to DB nor send emails. • Use the runAs method to test with different user contexts. • Test methods should execute Apex code with large data sets. Running tests in bulk mode will test the governor limits of your code.

Editor's Notes

  • #14 List<Integer> intList = new Integer[3]; intList[0] = 123; intList.add(456); Integer[] intArray = new List<Integer>(); intArray.add(456); intArray.set(0, 123);