Atl elevate programmatic developer slides
-
Upload
david-scruggs -
Category
Software
-
view
399 -
download
1
Transcript of Atl elevate programmatic developer slides
![Page 1: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/1.jpg)
Fast Track to Salesforce
Development
![Page 2: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/2.jpg)
Speakers
David Scruggs
@davescruggs
Stewart Loewen
![Page 3: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/3.jpg)
Safe Harbor
Safe harbor statement under the Private Securities Litigation Reform Act of 1995:
This presentation may contain forward-looking statements that involve risks, uncertainties, and assumptions. If any such uncertainties materialize or if any of
the assumptions proves incorrect, the results of salesforce.com, inc. could differ materially from the results expressed or implied by the forward-looking
statements we make. All statements other than statements of historical fact could be deemed forward-looking, including any projections of product or service
availability, subscriber growth, earnings, revenues, or other financial items and any statements regarding strategies or plans of management for future
operations, statements of belief, any statements concerning new, planned, or upgraded services or technology developments and customer contracts or use
of our services.
The risks and uncertainties referred to above include – but are not limited to – risks associated with developing and delivering new functionality for our
service, new products and services, our new business model, our past operating losses, possible fluctuations in our operating results and rate of growth,
interruptions or delays in our Web hosting, breach of our security measures, the outcome of intellectual property and other l itigation, risks associated with
possible mergers and acquisitions, the immature market in which we operate, our relatively limited operating history, our abi lity to expand, retain, and
motivate our employees and manage our growth, new releases of our service and successful customer deployment, our limited history reselling non-
salesforce.com products, and utilization and selling to larger enterprise customers. Further information on potential factors that could affect the financial
results of salesforce.com, inc. is included in our annual report on Form 10-Q for the most recent fiscal quarter ended July 31, 2012. This documents and
others containing important disclosures are available on the SEC Filings section of the Investor Information section of our Web site.
Any unreleased services or features referenced in this or other presentations, press releases or public statements are not currently available and may not be
delivered on time or at all. Customers who purchase our services should make the purchase decisions based upon features that are currently available.
Salesforce.com, inc. assumes no obligation and does not intend to update these forward-looking statements.
![Page 4: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/4.jpg)
Go Social!
@salesforcedevs
Salesforce
Developers
+Salesforce
Developers
Salesforce Developers
Salesforce
Developers
in/stewartloewen
In/dscruggs
@davescruggs
![Page 5: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/5.jpg)
Platform Overview
Setting Up the Conference Application
Writing Apex Classes
Accessing Data using SOQL
Writing Triggers
Writing Visualforce Pages
Writing Controller Extensions
Agenda
![Page 6: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/6.jpg)
http://bit.ly/elevate-intro
![Page 7: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/7.jpg)
Salesforce Platform is the Fastest Path from Idea to App
IdeaBuild App
Idea
buy &
setup
hardware
install
complex
software
define user
access
build & test
security
make it
mobile &
social
setup
reporting &
analytics
build
app
Traditional Platforms
6-12 Months?
App
App
![Page 8: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/8.jpg)
Salesforce1 Platform Services
Salesforce1 Platform
Force.com Heroku Exact Target
Salesforce1 Platform APIs
Salesforce1 App
Sales
Cloud
Service
Cloud
Marketing
CloudAppExchange
Custom
Apps
Partner
Apps
![Page 9: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/9.jpg)
Salesforce1 Mobile App
Salesforce on your phone
Customizable by
– Users
– Admins
– Developers
Supports
– Objects
– Visualforce
– Canvas
![Page 10: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/10.jpg)
Two Approaches to Development
Visualforce Pages
Visualforce Components
Apex Controllers
Apex Triggers
Metadata API
REST API
Bulk API
Formula Fields
Validation Rules
Workflows and Approvals
Custom Objects
Custom Fields
Relationships
Page Layouts
Record Types
User
Interface
Business
Logic
Data
Model
Declarative Approach Programmatic Approach
![Page 11: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/11.jpg)
The Conference App
Manage sessions and speakers
Automatically send confirmation emails
Customized user interface with Visualforce Pages
Upload speaker pictures
Flickr integration (Apex) to show conference pictures
Google Maps integration (JS) to show conference hotels
Companion app (JS + REST) for conference attendees
![Page 12: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/12.jpg)
Free Developer Environment
http://developer.salesforce.com/signup
![Page 13: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/13.jpg)
Lab 1: Install Your Developer Org
http://developer.salesforce.com/signup
![Page 14: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/14.jpg)
Module 2:
Setting Up the Conference App
![Page 15: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/15.jpg)
Salesforce Objects
Similar to Tables (with more metadata)
Standard objects out-of-the-box
– Account, Contact, Opportunity, …
You can add custom fields to standard objects
– Rating__c, Twitter__c, …
You can create custom objects
– i.e. Speaker__c, Session__c, Hotel__c
Custom objects have standard fields
– Id, Owner, LastModifiedDate, LastModifiedBy, …
![Page 16: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/16.jpg)
Rich Data Types
Auto Number
Formula
Roll-Up Summary
Lookup
Master-Detail
Checkbox
Currency
Date
Picklist (multi
select)
Text
Text Area
Text Area (Long)
Text Area (Rich)
Text (Encrypted)
URL
Date/Time
Geolocation
Number
Percent
Phone
Picklist
![Page 17: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/17.jpg)
Modeling Many-to-Many Relationships
A speaker can have
many session
assignments
A session can
have many
speaker
assignments
![Page 18: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/18.jpg)
Id
All objects are given an Id field
Globally unique Id is assigned at record creation
"Primary key" used to access records
![Page 19: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/19.jpg)
Record Name
Human readable / logical identifier
Text or Auto Number ("Intro to Apex" or SP-00002)
Uniqueness not enforced
![Page 20: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/20.jpg)
When you create an Object, you get…
A CRUD user interface
Instant Mobile App access (Salesforce1)
A REST API
Rich Metadata
Indexed search
![Page 21: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/21.jpg)
Lab 2: Importing the Workshop Assets
![Page 22: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/22.jpg)
Lab 2: Importing the Workshop Assets
![Page 23: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/23.jpg)
Module 3:
Writing Apex Classes
![Page 24: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/24.jpg)
What is Apex?
Salesforce platform language
Similar to Java
Object-oriented
Strongly typed
Classes and Interfaces
Cloud based compiling, debugging and unit testing
![Page 25: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/25.jpg)
Apex and Java
Same
Primitive data types
Flow control (if, for, while, …)
Exception handling
Collections: Lists, Sets, …
Different
Case insensitive
Single quote strings: 'Joe'
Id data type
Built-in support for data access
![Page 26: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/26.jpg)
Apex Class
public class MortgageCalculator {
}
public Double amount { get; set; }
public Double rate { get; set; }
public Integer years { get; set; }
public Double calculateMonthlyPayment() {
Integer months = years * 12;
Double monthlyRate = rate / (12 * 100);
return amount * (monthlyRate/
(1 - Math.pow(1 + monthlyRate, -months)));
}
![Page 27: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/27.jpg)
Development Tools
Developer Console
Force.com IDE (Eclipse Plugin)
Mavens Mate (Sublime Plugin)
Force CLI
![Page 28: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/28.jpg)
Developer Console
Browser Based IDE
Create Classes, Triggers, Pages
Execute Apex Anonymously
Execute SOQL Queries
Run Unit Tests
Review Debug Logs
![Page 29: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/29.jpg)
Lab 3: Creating an Apex Class
Create the EmailManager class
Send emails from the developer console
![Page 30: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/30.jpg)
Module 4:
Accessing Data with
SOQL and DML
![Page 31: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/31.jpg)
What's SOQL?
Salesforce Object Query language
Similar to SQL
Streamlined syntax to traverse object relationships
Built into Apex
![Page 32: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/32.jpg)
SELECT Id, Name, Phone
FROM Contact
![Page 33: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/33.jpg)
SELECT Id, Name, Phone
FROM Contact
WHERE Phone <> null
![Page 34: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/34.jpg)
SELECT Id, Name, Phone
FROM Contact
WHERE Phone <> null
AND Name LIKE '%rose%'
![Page 35: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/35.jpg)
SELECT Id, Name, Phone
FROM Contact
WHERE Phone <> null
AND Name LIKE '%rose%'
ORDER BY Name
![Page 36: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/36.jpg)
SELECT Id, Name, Phone
FROM Contact
WHERE Phone <> null
AND Name LIKE '%rose%'
ORDER BY Name
LIMIT 50
![Page 37: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/37.jpg)
Details to Master
SELECT Id, Name, Phone, Account.Name
FROM Contact
WHERE Phone <> null
AND Name LIKE '%rose%'
ORDER BY Name
LIMIT 50
![Page 38: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/38.jpg)
Master to Details
SELECT Name,
(SELECT FirstName, LastName, Phone
FROM Contacts)
FROM Account
![Page 39: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/39.jpg)
Executing SOQL in the Developer Console
![Page 40: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/40.jpg)
Inlining SOQL in Apex
Integer i = [SELECT Count() FROM Session__c];
![Page 41: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/41.jpg)
Inlining SOQL in Apex
String level = 'Advanced';
List<Session__c> sessions =
[SELECT Name, Level__c FROM Session__c
WHERE Level__c = :level];
![Page 42: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/42.jpg)
Inlining SOQL in Apex
List<String> levels = new List<String>();
levels.add('Intermediate');
levels.add('Advanced');
List<Session__c> sessions =
[SELECT Name, Level__c FROM Session__c
WHERE Level__c IN :levels];
![Page 43: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/43.jpg)
Inlining SOQL in Apex
for (Speaker__c s : [SELECT Email__c FROM Speaker__c])
{
System.debug(s.email__c);
}
![Page 44: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/44.jpg)
What's DML?
Data Manipulation Language
Language used to create, update, delete records
![Page 45: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/45.jpg)
insert
Session__c session = new Session__c();
session.name = 'Apex 101';
session.level__c = 'Beginner';
insert session;
![Page 46: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/46.jpg)
insert
Session__c session = new Session__c(
name = 'Apex 201',
level__c = 'Intermediate'
);
insert session;
![Page 47: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/47.jpg)
update
String oldName = 'Apex 101';
String newName = 'Apex for Beginners';
Session__c session =
[SELECT Id, Name FROM Session__c
WHERE Name=:oldName];
session.name = newName;
update session;
![Page 48: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/48.jpg)
delete
String name = 'Testing 501';
Session__c session =
[SELECT Name FROM Session__c
WHERE Name=:name];
delete session;
![Page 49: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/49.jpg)
Lab 4: Accessing Data using SOQL and DML
Execute SOQL statements in the Query Editor
Execute DML statements in the Anonymous Window
![Page 50: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/50.jpg)
Module 5:
Writing Triggers
![Page 51: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/51.jpg)
What's a Trigger?
Apex code executed on database events
Before or after:
– Insert
– Update
– Delete
– Undelete
![Page 52: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/52.jpg)
Before or After?
Before
– Update or validate values before they are saved to the database
– Example: Prevent double-booking of a speaker
After
– Access values set by the database (Id, lastUpdated, …)
– Example: Send speaker confirmation email
![Page 53: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/53.jpg)
Bulk Mode
Triggers work on lists of records, not single records
This is to support bulk operations
– Data Import, Bulk API, etc.
Context variables provide access to old and new values:
– Trigger.old and Trigger.new (List)
– Trigger.oldMap and Trigger.newMap (Map)
![Page 54: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/54.jpg)
Example 1
trigger WelcomeKit on Account (after insert) {
List<Case> cases = new List<Case>();
for (Account account : Trigger.new) {
Case case = new Case();
case.Subject = 'Mail Welcome Kit';
case.Account.Id = account.Id;
cases.add(case);
}
insert cases;
}
![Page 55: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/55.jpg)
Example 2
trigger on Account (before update) {
for (Account acc: Trigger.New) {
// Compare new value with old value
if (acc.Rating != Trigger.oldMap.get(acc.Id).Rating) {
// Your Logic
}
}
}
![Page 56: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/56.jpg)
Workflow vs Trigger
Workflow Trigger
Created with Clicks Code
What can it do • Update field
• Send email
• Create task
• Send outbound message
• Launch flow (flow trigger)
~ Anything (e.g.
create/delete records,
REST callout, etc.)
Cross-object field updates Limited (detail -> master) Any
![Page 57: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/57.jpg)
Lab 5: Writing Triggers
Write the SendConfirmationEmail trigger
Write the RejectDoubleBooking trigger
![Page 58: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/58.jpg)
Module 6:
Writing Visualforce Pages
![Page 59: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/59.jpg)
What's a Visualforce Page?
HTML page with tags executed at the server-side to
generate dynamic content
Similar to JSP and ASP
Can leverage JavaScript and CSS libraries
The View in MVC architecture
![Page 60: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/60.jpg)
Model-View-Controller
ModelData + Rules
ControllerView-Model
interactions
ViewUI code
Separation of concerns
– No data access code in view
– No view code in controller
Benefits
– Minimize impact of changes
– More reusable components
![Page 61: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/61.jpg)
Model-View-Controller in Salesforce
View• Standard Pages
• Visualforce Pages
• External apps
Controller• Standard Controllers
• Controller Extensions
• Custom Controllers
Model• Objects
• Triggers (Apex)
• Classes (Apex)
![Page 62: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/62.jpg)
Component Library
Presentation tags
– <apex:pageBlock title="My Account Contacts">
Fine grained data tags
– <apex:outputField value="{!contact.firstname}">
– <apex:inputField value="{!contact.firstname}">
Coarse grained data tags
– <apex:detail>
– <apex:pageBlockTable>
Action tags
– <apex:commandButton action="{!save}" >
![Page 63: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/63.jpg)
Expression Language
Anything inside of {! } is evaluated as an expression
Same expression language as Formulas
$ provides access to global variables (User,
RemoteAction, Resource, …)
– {! $User.FirstName } {! $User.LastName }
![Page 64: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/64.jpg)
Example 1
<apex:page>
<h1>Hello, {!$User.FirstName}</h1>
</apex:page>
![Page 65: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/65.jpg)
Standard Controller
A standard controller is available for all objects
– You don't have to write it!
Provides standard CRUD operations
– Create, Update, Delete, Field Access, etc.
Can be extended with more capabilities (next module)
Uses id query string parameter in URL to access object
![Page 66: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/66.jpg)
Example 2
<apex:page standardController="Contact">
<apex:form>
<apex:inputField value="{!contact.firstname}"/>
<apex:inputField value="{!contact.lastname}"/>
<apex:commandButton action="{!save}" value="Save"/>
</apex:form>
</apex:page>Function in
standard controller
Standard controller
object
![Page 67: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/67.jpg)
Templates
Embedded in Page
Layouts
Generate PDFs
Custom Tabs
Mobile
Interfaces
Page Overrides
Where can I use Visualforce?
![Page 68: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/68.jpg)
Lab 6: Writing Visualforce Pages
Write the SpeakerForm Visualforce page
Set it as default for creating and editing speakers
![Page 69: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/69.jpg)
Module 7:
Writing Controller Extensions
and Custom Controllers
![Page 70: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/70.jpg)
What's a Controller Extension?
Custom class written in Apex
Works on the same object as the standard controller
Can override standard controller behavior
Can add new capabilities
![Page 71: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/71.jpg)
Defining a Controller Extension
<apex:page standardController="Speaker__c"
extensions="SpeakerCtrlExt">
Provides basic
CRUD
Overrides standard
actions and/or provide
additional capabilities
![Page 72: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/72.jpg)
Anatomy of a Controller Extension
public class SpeakerCtrlExt {
private final Speaker__c speaker;
private ApexPages.StandardController stdController;
public SpeakerCtrlExt (ApexPages.StandardController ctrl) {
this.stdController = ctrl;
this.speaker = (Speaker__c)ctrl.getRecord();
}
// method overrides
// custom methods
}
![Page 73: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/73.jpg)
What's a Custom Controller?
Custom class written in Apex
Doesn't work on a specific object
Provides custom data
Provides custom behaviors
![Page 74: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/74.jpg)
Defining a Custom Controller
<apex:page controller="FlickrController">
![Page 75: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/75.jpg)
Custom Controller Example
public with sharing class FlickrController {
public FlickrList getPictures() {
HttpRequest req = new HttpRequest();
req.setMethod('GET');
req.setEndpoint('http://api.flickr.com/services/feeds/');
HTTP http = new HTTP();
HTTPResponse res = http.send(req);
return (FlickrList) JSON.deserialize(res.getBody(),
FlickrList.class);
}
}
![Page 76: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/76.jpg)
Lab 7: Writing a Controller Extension
Write a Controller Extension that supports Picture
Upload
![Page 77: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/77.jpg)
Advanced Salesforce
Development Workshop
![Page 78: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/78.jpg)
Setting Up the Conference Application
Using JavaScript in Visualforce Pages
Using the Salesforce1 Platform APIs
Using Static Resources
Using Canvas Applications
Testing
Batching and Scheduling
Agenda
![Page 79: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/79.jpg)
The Conference App
Manage sessions and speakers
Automatically send confirmation emails
Customized user interface with Visualforce Pages
Upload speaker pictures
Flickr integration (Apex) to show conference pictures
Google Maps integration (JS) to show conference hotels
Companion app (JS + REST) for conference attendees
![Page 80: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/80.jpg)
http://bit.ly/elevate-advanced
![Page 81: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/81.jpg)
Lab 2: Importing the Workshop Assets
![Page 82: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/82.jpg)
Lab 2: Importing the Workshop Assets
![Page 83: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/83.jpg)
Module 3:
Using JavaScript in
Visualforce Pages
![Page 84: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/84.jpg)
Why Use JavaScript?
Build Engaging User Experiences
Leverage JavaScript Libraries
Build Custom Applications
![Page 85: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/85.jpg)
JavaScript in Visualforce Pages
JavaScript Remoting
Remote Objects
(REST)
Visualforce Page
![Page 86: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/86.jpg)
Examples
![Page 87: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/87.jpg)
JavaScript Remoting - Server-Side
global with sharing class HotelRemoter {
@RemoteAction
global static List<Hotel__c> findAll() {
return [SELECT Id,
Name,
Location__Latitude__s,
Location__Longitude__s
FROM Hotel__c];
}
}
![Page 88: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/88.jpg)
"global with sharing"?
global
– Available from outside of the application
with sharing
– Run code with current user permissions. (Apex code runs in
system context by default -- with access to all objects and fields)
![Page 89: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/89.jpg)
JavaScript Remoting - Visualforce Page
<script>
Visualforce.remoting.Manager.invokeAction(
'{!$RemoteAction.HotelRemoter.findAll}',
function (result, event) {
if (event.status) {
for (var i = 0; i < result.length; i++) {
var lat = result[i].Location__Latitude__s;
var lng = result[i].Location__Longitude__s;
addMarker(lat, lng);
}
} else {
alert(event.message);
}
}
);
</script>
![Page 90: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/90.jpg)
Using JavaScript and CSS Libraries
Hosted elsewhere
<script src="https://maps.googleapis.com/maps/api/js"></script>
Hosted in Salesforce
– Upload individual file or Zip file as Static Resource
– Reference asset using special tags
– Covered in Module 5
![Page 91: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/91.jpg)
Lab 3: Using JavaScript in Visualforce Pages
Write the HotelMap Visualforce Page
![Page 92: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/92.jpg)
Module 4:
Using the REST APIs
![Page 93: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/93.jpg)
When?
Get access to Salesforce data from outside Salesforce:
Integrate Salesforce in existing apps
Build consumer apps
Device integration (Internet of Things)
![Page 94: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/94.jpg)
Mobile SDK Example
REST APIs
OAuth
![Page 95: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/95.jpg)
Browser Cross-Origin Restrictions
REST APIs
app.js
index.html
OAuth
HTTP Server
Cross Origin Policy
![Page 96: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/96.jpg)
Using a Proxy
app.js
index.html
OAuth
REST APIs
HTTP Server
Proxy
![Page 97: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/97.jpg)
http://bit.ly/trysoql
![Page 98: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/98.jpg)
https://contact-force.herokuapp.com
![Page 99: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/99.jpg)
Connected App
![Page 100: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/100.jpg)
Libraries
ForceJS
– Simple Oauth + REST toolkit without dependency
ForceTK
– Salesforce REST API Toolkit
Nforce
– node.js a REST API wrapper
ngForce
– Visualforce Remoting integration in AngularJS
JSForce
![Page 101: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/101.jpg)
Lab 4: Using the REST APIs
Create a consumer app hosted outside Salesforce
![Page 102: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/102.jpg)
Windows Users
After installing Node.js:
1. Add c:\Program Files\Nodejs to your path
or
Run "C:\Program Files\Nodejs\npm" install
2. Create an "npm" directory in
C:\Users\[yourname]\Appdata\Roaming
![Page 103: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/103.jpg)
Module 5:
Using Static Resources
![Page 104: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/104.jpg)
What are Static Resources?
Files uploaded to Salesforce instance for use in
Visualforce pages
– .js
– .css
– .jpg, .png, .gif, etc.
Can be uploaded individually or as archive (.zip or .jar)
![Page 105: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/105.jpg)
Static Resources
![Page 106: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/106.jpg)
Visualforce and HTML Page Generation
By default, Visualforce generates HTML page elements:
– <html>
– <head>
– <body>
<apex:> tags ensure corresponding HTML elements are
inserted at the right place
– <apex:stylesheet>
– <apex:includeScript>
![Page 107: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/107.jpg)
Referencing Static Resources
// Single file
<apex:stylesheet value="{!$Resource.bootstrap}"/>
<apex:includeScript value="{!$Resource.jquery}"/>
<apex:image url="{!$Resource.logo}"/>
// ZIP file
<apex:stylesheet value="{!URLFOR($Resource.assets, 'css/main.css')}"/>
<apex:image url="{!URLFOR($Resource.assets, 'img/logo.png')}"/>
<apex:includeScript value="{!URLFOR($Resource.assets, 'js/app.js')}"/>
![Page 108: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/108.jpg)
Controlling HTML Page Generation
You can also take full control over HTML elements
generation and position:
<apex:page docType="html"
applyHtmlTag="false"
applyBodyTag="false">
… and use standard HTML tags
– <link rel="stylesheet" href="…">
– <script src="…">
![Page 109: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/109.jpg)
Referencing Static Resources
// Single file
<link href="{!$Resource.bootstrap}" rel="stylesheet"/>
<img src="{!$Resource.logo}"/>
<script src="{!$Resource.jquery}"></script>
// ZIP file
<link href="{!URLFOR($Resource.assets, 'css/main.css')}" rel="stylesheet"/>
<img src="{!URLFOR($Resource.assets, 'img/logo.png')}"/>
<script src="{!URLFOR($Resource.assets, 'js/app.js')}"></script>
![Page 110: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/110.jpg)
Lab 5: Static Resources
Host single page application in Visualforce page
![Page 111: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/111.jpg)
Module 6:
Using Canvas Applications
![Page 112: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/112.jpg)
What is a Canvas App?
A web app integrated in your Salesforce environment
Can be written in any language
– Java, .NET, PHP, Ruby on Rails, Node.js, etc.
Transparently authenticated
Context aware (logged in user, current object, etc.)
![Page 113: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/113.jpg)
Use Cases
Internal App
Third-Party / Partner App
External systems with web facade
![Page 114: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/114.jpg)
Where Can It Be Integrated?
Publisher
Page Layouts
Visualforce Pages
Tabs
Mobile Cards
![Page 115: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/115.jpg)
Defining a Canvas App
![Page 116: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/116.jpg)
Transparent Authentication
When loading Canvas app, Salesforce instance posts
Base64 encoded data to app endpoint including:
– Authenticated token
– Context (logged in user, current object, etc)
App decodes data using client secret
Can use authenticated token to make REST API calls
![Page 117: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/117.jpg)
Node.js example
var decode = require('salesforce-signed-request');
var secret = process.env.CONSUMER_SECRET;
app.post('/signedrequest', function(req, res) {
var signedRequest = req.body.signed_request;
var decodedRequest = decode(signedRequest, secret);
var oauthToken = decodedRequest.client.oauthToken;
var instanceUrl = decodedRequest.client.instanceUrl;
var context = decodedRequest.context;
});
![Page 118: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/118.jpg)
Lab 6: Canvas
Deploy Node.js web app to Heroku
Integrate app in Contact page layout
![Page 119: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/119.jpg)
Module 7:
Writing Unit Tests
![Page 120: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/120.jpg)
Unit Testing
Code to test code
Increases quality and predictability
Unit test coverage is required to move code to production
– Must have at least 75% of code covered
– Coverage = lines of code exercised by tests / total line of code
![Page 121: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/121.jpg)
Anatomy of a Test Class
@isTest
private class myClass {
static testMethod void myTest() {
// 1. Prepare temporary data
// 2. Start Test
// 3. Execute some code
// 4. Stop Test
// 5. Assert
}
}
![Page 122: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/122.jpg)
Create Temporary Data
Datetime now = System.now();
// Create speaker
Speaker__c sp = new Speaker__c(First_Name__c='Al', Last_Name__c='Smith');
insert sp;
// Create two sessions starting at the same time
Session__c s1 = new Session__c(Name='Session1', Session_Date__c=now);
insert s1;
Session__c s2 = new Session__c(Name='Session2', Session_Date__c=now);
insert s2;
// Book speaker for session1
Session_Speaker__c booking1 =
new Session_Speaker__c(Session__c=s1.Id, Speaker__c=sp.Id);
insert booking1;
![Page 123: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/123.jpg)
Test and Assert
Test.startTest();
// Try to book speaker for session2
Session_Speaker__c booking2=
new Session_Speaker__c(Session__c=s2.Id, Speaker__c=sp.Id);
Database.SaveResult result = Database.insert(booking2, false);
Test.stopTest();
// Insert should fail: can't book same speaker for 2 sessions happening
// at same time
System.assert(!result.isSuccess());
![Page 124: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/124.jpg)
Running Tests
![Page 125: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/125.jpg)
Lab 7: Unit Testing
Write the TestDoubleBooking class
Run the test
![Page 126: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/126.jpg)
Module 8:
Batching and Scheduling
![Page 127: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/127.jpg)
What's a Batch?
Long-running process that runs without manual
intervention
Started programmatically
![Page 128: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/128.jpg)
Defining a Batch Job
global class SendReminderEmail implements Database.Batchable {
global SendReminderEmail(String query, String subject, String body) {
// Constructor: accept parameters
}
global Database.QueryLocator start(Database.BatchableContext bc) {
// Select scope (records to process)
}
global void execute(Database.BatchableContext bc, List<Speaker__c> scope) {
// Process data
}
global void finish(Database.BatchableContext bc) {
// Post processing operations
}
}
![Page 129: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/129.jpg)
Running the Batch Job
String q = 'SELECT First_Name__c, Last_Name__c, Email__c ' +
'FROM Speaker__c WHERE Email__c != null';
SendReminderEmail batch = new SendReminderEmail(q,
'Final Reminder', 'The conference starts next Monday');
Database.executeBatch(batch);
![Page 130: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/130.jpg)
What's Scheduled Job?
Unattended background program execution
Occurs at a specified time
Optionally repeated at a specified interval
![Page 131: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/131.jpg)
Defining a Scheduled Job
global class ScheduledEmail implements Schedulable {
global void execute(SchedulableContext sc) {
String q = 'SELECT First_Name__c, Last_Name__c, Email__c ' +
'FROM Speaker__c WHERE Email__c != null';
SendReminderEmail batch = new SendReminderEmail(q,
'Final Reminder', 'The conference starts next Monday');
Database.executeBatch(batch);
}
}
![Page 132: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/132.jpg)
Scheduling the Job (using Code)
ScheduledEmail job = new ScheduledEmail();
// Run at 8AM on February 10th
// (Seconds Minutes Hours Day_of_month Month Day_of_week Years)
// Can use wildcards
String schedule = '0 0 8 10 2 ?';
String jobId = System.schedule('Final reminder', schedule, job);
![Page 133: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/133.jpg)
Scheduling the Job (using Clicks)
![Page 134: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/134.jpg)
Monitoring Scheduled Jobs
![Page 135: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/135.jpg)
Lab 8: Batching and Scheduling
Write the SendReminderEmail class
Run the batch
![Page 136: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/136.jpg)
Next Steps in Your Developer Journey
http://developer.salesforce.com
Developer Forums
TrailHead
Webinars and Videos
Events
These slides are at http://slidesha.re/14DG6RA
![Page 137: Atl elevate programmatic developer slides](https://reader034.fdocuments.net/reader034/viewer/2022052602/55a417ad1a28aba26f8b4606/html5/thumbnails/137.jpg)
Survey
Your feedback is crucial to the success
of our workshops. Thank you!
http://bit.ly/ATL115