Fast Track to Salesforce
Development
Speakers
David Scruggs
@davescruggs
Stewart Loewen
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 litigation, risks associated with
possible mergers and acquisitions, the immature market in which we operate, our relatively limited operating history, our ability 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.
Go Social!
@salesforcedevs
Salesforce
Developers
+Salesforce
Developers
Salesforce Developers
Salesforce
Developers
in/stewartloewen
In/dscruggs
@davescruggs
 Platform Overview
 Setting Up the Conference Application
 Writing Apex Classes
 Accessing Data using SOQL
 Writing Triggers
 Writing Visualforce Pages
 Writing Controller Extensions
Agenda
http://bit.ly/elevate-intro
Salesforce Platform is the Fastest Path from Idea to App
Idea
Build 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
Salesforce1 Platform Services
Salesforce1 Platform
Force.com Heroku Exact Target
Salesforce1 Platform APIs
Salesforce1 App
Sales
Cloud
Service
Cloud
Marketing
Cloud
AppExchange
Custom
Apps
Partner
Apps
Salesforce1 Mobile App
 Salesforce on your phone
 Customizable by
– Users
– Admins
– Developers
 Supports
– Objects
– Visualforce
– Canvas
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
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
Free Developer Environment
http://developer.salesforce.com/signup
Lab 1: Install Your Developer Org
http://developer.salesforce.com/signup
Module 2:
Setting Up the Conference App
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, …
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
 Email
 Geolocation
 Number
 Percent
 Phone
 Picklist
Modeling Many-to-Many Relationships
A speaker can have
many session
assignments
A session can
have many
speaker
assignments
Id
 All objects are given an Id field
 Globally unique Id is assigned at record creation
 "Primary key" used to access records
Record Name
 Human readable / logical identifier
 Text or Auto Number ("Intro to Apex" or SP-00002)
 Uniqueness not enforced
When you create an Object, you get…
 A CRUD user interface
 Instant Mobile App access (Salesforce1)
 A REST API
 Rich Metadata
 Indexed search
Lab 2: Importing the Workshop Assets
Lab 2: Importing the Workshop Assets
Module 3:
Writing Apex Classes
What is Apex?
 Salesforce platform language
 Similar to Java
 Object-oriented
 Strongly typed
 Classes and Interfaces
 Cloud based compiling, debugging and unit testing
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
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)));
}
Development Tools
 Developer Console
 Force.com IDE (Eclipse Plugin)
 Mavens Mate (Sublime Plugin)
 Force CLI
Developer Console
 Browser Based IDE
 Create Classes, Triggers, Pages
 Execute Apex Anonymously
 Execute SOQL Queries
 Run Unit Tests
 Review Debug Logs
Lab 3: Creating an Apex Class
 Create the EmailManager class
 Send emails from the developer console
Module 4:
Accessing Data with
SOQL and DML
What's SOQL?
 Salesforce Object Query language
 Similar to SQL
 Streamlined syntax to traverse object relationships
 Built into Apex
SELECT Id, Name, Phone
FROM Contact
SELECT Id, Name, Phone
FROM Contact
WHERE Phone <> null
SELECT Id, Name, Phone
FROM Contact
WHERE Phone <> null
AND Name LIKE '%rose%'
SELECT Id, Name, Phone
FROM Contact
WHERE Phone <> null
AND Name LIKE '%rose%'
ORDER BY Name
SELECT Id, Name, Phone
FROM Contact
WHERE Phone <> null
AND Name LIKE '%rose%'
ORDER BY Name
LIMIT 50
Details to Master
SELECT Id, Name, Phone, Account.Name
FROM Contact
WHERE Phone <> null
AND Name LIKE '%rose%'
ORDER BY Name
LIMIT 50
Master to Details
SELECT Name,
(SELECT FirstName, LastName, Phone
FROM Contacts)
FROM Account
Executing SOQL in the Developer Console
Inlining SOQL in Apex
Integer i = [SELECT Count() FROM Session__c];
Inlining SOQL in Apex
String level = 'Advanced';
List<Session__c> sessions =
[SELECT Name, Level__c FROM Session__c
WHERE Level__c = :level];
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];
Inlining SOQL in Apex
for (Speaker__c s : [SELECT Email__c FROM Speaker__c])
{
System.debug(s.email__c);
}
What's DML?
 Data Manipulation Language
 Language used to create, update, delete records
insert
Session__c session = new Session__c();
session.name = 'Apex 101';
session.level__c = 'Beginner';
insert session;
insert
Session__c session = new Session__c(
name = 'Apex 201',
level__c = 'Intermediate'
);
insert session;
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;
delete
String name = 'Testing 501';
Session__c session =
[SELECT Name FROM Session__c
WHERE Name=:name];
delete session;
Lab 4: Accessing Data using SOQL and DML
 Execute SOQL statements in the Query Editor
 Execute DML statements in the Anonymous Window
Module 5:
Writing Triggers
What's a Trigger?
 Apex code executed on database events
 Before or after:
– Insert
– Update
– Delete
– Undelete
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
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)
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;
}
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
}
}
}
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
Lab 5: Writing Triggers
 Write the SendConfirmationEmail trigger
 Write the RejectDoubleBooking trigger
Module 6:
Writing Visualforce Pages
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
Model-View-Controller
Model
Data + Rules
Controller
View-Model
interactions
View
UI code
 Separation of concerns
– No data access code in view
– No view code in controller
 Benefits
– Minimize impact of changes
– More reusable components
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)
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}" >
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 }
Example 1
<apex:page>
<h1>Hello, {!$User.FirstName}</h1>
</apex:page>
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
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
Email
Templates
Embedded in Page
Layouts
Generate PDFs
Custom Tabs
Mobile
Interfaces
Page Overrides
Where can I use Visualforce?
Lab 6: Writing Visualforce Pages
 Write the SpeakerForm Visualforce page
 Set it as default for creating and editing speakers
Module 7:
Writing Controller Extensions
and Custom Controllers
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
Defining a Controller Extension
<apex:page standardController="Speaker__c"
extensions="SpeakerCtrlExt">
Provides basic
CRUD
Overrides standard
actions and/or provide
additional capabilities
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
}
What's a Custom Controller?
 Custom class written in Apex
 Doesn't work on a specific object
 Provides custom data
 Provides custom behaviors
Defining a Custom Controller
<apex:page controller="FlickrController">
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);
}
}
Lab 7: Writing a Controller Extension
 Write a Controller Extension that supports Picture
Upload
Advanced Salesforce
Development Workshop
 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
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
http://bit.ly/elevate-advanced
Lab 2: Importing the Workshop Assets
Lab 2: Importing the Workshop Assets
Module 3:
Using JavaScript in
Visualforce Pages
Why Use JavaScript?
 Build Engaging User Experiences
 Leverage JavaScript Libraries
 Build Custom Applications
JavaScript in Visualforce Pages
JavaScript Remoting
Remote Objects
(REST)
Visualforce Page
Examples
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];
}
}
"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)
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>
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
Lab 3: Using JavaScript in Visualforce Pages
 Write the HotelMap Visualforce Page
Module 4:
Using the REST APIs
When?
Get access to Salesforce data from outside Salesforce:
 Integrate Salesforce in existing apps
 Build consumer apps
 Device integration (Internet of Things)
Mobile SDK Example
REST APIs
OAuth
Browser Cross-Origin Restrictions
REST APIs
app.js
index.html
OAuth
HTTP Server
Cross Origin Policy
Using a Proxy
app.js
index.html
OAuth
REST APIs
HTTP Server
Proxy
http://bit.ly/trysoql
https://contact-force.herokuapp.com
Connected App
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
Lab 4: Using the REST APIs
 Create a consumer app hosted outside Salesforce
Windows Users
After installing Node.js:
1. Add c:Program FilesNodejs to your path
or
Run "C:Program FilesNodejsnpm" install
2. Create an "npm" directory in
C:Users[yourname]AppdataRoaming
Module 5:
Using Static Resources
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)
Static Resources
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>
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')}"/>
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="…">
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>
Lab 5: Static Resources
 Host single page application in Visualforce page
Module 6:
Using Canvas Applications
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.)
Use Cases
 Internal App
 Third-Party / Partner App
 External systems with web facade
Where Can It Be Integrated?
 Publisher
 Page Layouts
 Visualforce Pages
 Tabs
 Mobile Cards
Defining a Canvas App
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
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;
});
Lab 6: Canvas
 Deploy Node.js web app to Heroku
 Integrate app in Contact page layout
Module 7:
Writing Unit Tests
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
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
}
}
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;
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());
Running Tests
Lab 7: Unit Testing
 Write the TestDoubleBooking class
 Run the test
Module 8:
Batching and Scheduling
What's a Batch?
 Long-running process that runs without manual
intervention
 Started programmatically
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
}
}
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);
What's Scheduled Job?
 Unattended background program execution
 Occurs at a specified time
 Optionally repeated at a specified interval
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);
}
}
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);
Scheduling the Job (using Clicks)
Monitoring Scheduled Jobs
Lab 8: Batching and Scheduling
 Write the SendReminderEmail class
 Run the batch
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
Survey
Your feedback is crucial to the success
of our workshops. Thank you!
http://bit.ly/ATL115

Atl elevate programmatic developer slides

  • 1.
    Fast Track toSalesforce Development
  • 2.
  • 3.
    Safe Harbor Safe harborstatement 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 litigation, risks associated with possible mergers and acquisitions, the immature market in which we operate, our relatively limited operating history, our ability 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.
  • 4.
  • 5.
     Platform Overview Setting Up the Conference Application  Writing Apex Classes  Accessing Data using SOQL  Writing Triggers  Writing Visualforce Pages  Writing Controller Extensions Agenda
  • 6.
  • 7.
    Salesforce Platform isthe Fastest Path from Idea to App Idea Build 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
  • 8.
    Salesforce1 Platform Services Salesforce1Platform Force.com Heroku Exact Target Salesforce1 Platform APIs Salesforce1 App Sales Cloud Service Cloud Marketing Cloud AppExchange Custom Apps Partner Apps
  • 9.
    Salesforce1 Mobile App Salesforce on your phone  Customizable by – Users – Admins – Developers  Supports – Objects – Visualforce – Canvas
  • 10.
    Two Approaches toDevelopment 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
  • 11.
    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
  • 12.
  • 13.
    Lab 1: InstallYour Developer Org http://developer.salesforce.com/signup
  • 14.
    Module 2: Setting Upthe Conference App
  • 15.
    Salesforce Objects  Similarto 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, …
  • 16.
    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  Email  Geolocation  Number  Percent  Phone  Picklist
  • 17.
    Modeling Many-to-Many Relationships Aspeaker can have many session assignments A session can have many speaker assignments
  • 18.
    Id  All objectsare given an Id field  Globally unique Id is assigned at record creation  "Primary key" used to access records
  • 19.
    Record Name  Humanreadable / logical identifier  Text or Auto Number ("Intro to Apex" or SP-00002)  Uniqueness not enforced
  • 20.
    When you createan Object, you get…  A CRUD user interface  Instant Mobile App access (Salesforce1)  A REST API  Rich Metadata  Indexed search
  • 21.
    Lab 2: Importingthe Workshop Assets
  • 22.
    Lab 2: Importingthe Workshop Assets
  • 23.
  • 24.
    What is Apex? Salesforce platform language  Similar to Java  Object-oriented  Strongly typed  Classes and Interfaces  Cloud based compiling, debugging and unit testing
  • 25.
    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
  • 26.
    Apex Class public classMortgageCalculator { } 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))); }
  • 27.
    Development Tools  DeveloperConsole  Force.com IDE (Eclipse Plugin)  Mavens Mate (Sublime Plugin)  Force CLI
  • 28.
    Developer Console  BrowserBased IDE  Create Classes, Triggers, Pages  Execute Apex Anonymously  Execute SOQL Queries  Run Unit Tests  Review Debug Logs
  • 29.
    Lab 3: Creatingan Apex Class  Create the EmailManager class  Send emails from the developer console
  • 30.
    Module 4: Accessing Datawith SOQL and DML
  • 31.
    What's SOQL?  SalesforceObject Query language  Similar to SQL  Streamlined syntax to traverse object relationships  Built into Apex
  • 32.
    SELECT Id, Name,Phone FROM Contact
  • 33.
    SELECT Id, Name,Phone FROM Contact WHERE Phone <> null
  • 34.
    SELECT Id, Name,Phone FROM Contact WHERE Phone <> null AND Name LIKE '%rose%'
  • 35.
    SELECT Id, Name,Phone FROM Contact WHERE Phone <> null AND Name LIKE '%rose%' ORDER BY Name
  • 36.
    SELECT Id, Name,Phone FROM Contact WHERE Phone <> null AND Name LIKE '%rose%' ORDER BY Name LIMIT 50
  • 37.
    Details to Master SELECTId, Name, Phone, Account.Name FROM Contact WHERE Phone <> null AND Name LIKE '%rose%' ORDER BY Name LIMIT 50
  • 38.
    Master to Details SELECTName, (SELECT FirstName, LastName, Phone FROM Contacts) FROM Account
  • 39.
    Executing SOQL inthe Developer Console
  • 40.
    Inlining SOQL inApex Integer i = [SELECT Count() FROM Session__c];
  • 41.
    Inlining SOQL inApex String level = 'Advanced'; List<Session__c> sessions = [SELECT Name, Level__c FROM Session__c WHERE Level__c = :level];
  • 42.
    Inlining SOQL inApex 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];
  • 43.
    Inlining SOQL inApex for (Speaker__c s : [SELECT Email__c FROM Speaker__c]) { System.debug(s.email__c); }
  • 44.
    What's DML?  DataManipulation Language  Language used to create, update, delete records
  • 45.
    insert Session__c session =new Session__c(); session.name = 'Apex 101'; session.level__c = 'Beginner'; insert session;
  • 46.
    insert Session__c session =new Session__c( name = 'Apex 201', level__c = 'Intermediate' ); insert session;
  • 47.
    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;
  • 48.
    delete String name ='Testing 501'; Session__c session = [SELECT Name FROM Session__c WHERE Name=:name]; delete session;
  • 49.
    Lab 4: AccessingData using SOQL and DML  Execute SOQL statements in the Query Editor  Execute DML statements in the Anonymous Window
  • 50.
  • 51.
    What's a Trigger? Apex code executed on database events  Before or after: – Insert – Update – Delete – Undelete
  • 52.
    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
  • 53.
    Bulk Mode  Triggerswork 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)
  • 54.
    Example 1 trigger WelcomeKiton 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; }
  • 55.
    Example 2 trigger onAccount (before update) { for (Account acc: Trigger.New) { // Compare new value with old value if (acc.Rating != Trigger.oldMap.get(acc.Id).Rating) { // Your Logic } } }
  • 56.
    Workflow vs Trigger WorkflowTrigger 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
  • 57.
    Lab 5: WritingTriggers  Write the SendConfirmationEmail trigger  Write the RejectDoubleBooking trigger
  • 58.
  • 59.
    What's a VisualforcePage?  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
  • 60.
    Model-View-Controller Model Data + Rules Controller View-Model interactions View UIcode  Separation of concerns – No data access code in view – No view code in controller  Benefits – Minimize impact of changes – More reusable components
  • 61.
    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)
  • 62.
    Component Library  Presentationtags – <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}" >
  • 63.
    Expression Language  Anythinginside of {! } is evaluated as an expression  Same expression language as Formulas  $ provides access to global variables (User, RemoteAction, Resource, …) – {! $User.FirstName } {! $User.LastName }
  • 64.
  • 65.
    Standard Controller  Astandard 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
  • 66.
    Example 2 <apex:page standardController="Contact"> <apex:form> <apex:inputFieldvalue="{!contact.firstname}"/> <apex:inputField value="{!contact.lastname}"/> <apex:commandButton action="{!save}" value="Save"/> </apex:form> </apex:page> Function in standard controller Standard controller object
  • 67.
    Email Templates Embedded in Page Layouts GeneratePDFs Custom Tabs Mobile Interfaces Page Overrides Where can I use Visualforce?
  • 68.
    Lab 6: WritingVisualforce Pages  Write the SpeakerForm Visualforce page  Set it as default for creating and editing speakers
  • 69.
    Module 7: Writing ControllerExtensions and Custom Controllers
  • 70.
    What's a ControllerExtension?  Custom class written in Apex  Works on the same object as the standard controller  Can override standard controller behavior  Can add new capabilities
  • 71.
    Defining a ControllerExtension <apex:page standardController="Speaker__c" extensions="SpeakerCtrlExt"> Provides basic CRUD Overrides standard actions and/or provide additional capabilities
  • 72.
    Anatomy of aController 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 }
  • 73.
    What's a CustomController?  Custom class written in Apex  Doesn't work on a specific object  Provides custom data  Provides custom behaviors
  • 74.
    Defining a CustomController <apex:page controller="FlickrController">
  • 75.
    Custom Controller Example publicwith 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); } }
  • 76.
    Lab 7: Writinga Controller Extension  Write a Controller Extension that supports Picture Upload
  • 77.
  • 78.
     Setting Upthe Conference Application  Using JavaScript in Visualforce Pages  Using the Salesforce1 Platform APIs  Using Static Resources  Using Canvas Applications  Testing  Batching and Scheduling Agenda
  • 79.
    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
  • 80.
  • 81.
    Lab 2: Importingthe Workshop Assets
  • 82.
    Lab 2: Importingthe Workshop Assets
  • 83.
    Module 3: Using JavaScriptin Visualforce Pages
  • 84.
    Why Use JavaScript? Build Engaging User Experiences  Leverage JavaScript Libraries  Build Custom Applications
  • 85.
    JavaScript in VisualforcePages JavaScript Remoting Remote Objects (REST) Visualforce Page
  • 86.
  • 87.
    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]; } }
  • 88.
    "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)
  • 89.
    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>
  • 90.
    Using JavaScript andCSS 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
  • 91.
    Lab 3: UsingJavaScript in Visualforce Pages  Write the HotelMap Visualforce Page
  • 92.
  • 93.
    When? Get access toSalesforce data from outside Salesforce:  Integrate Salesforce in existing apps  Build consumer apps  Device integration (Internet of Things)
  • 94.
  • 95.
    Browser Cross-Origin Restrictions RESTAPIs app.js index.html OAuth HTTP Server Cross Origin Policy
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
    Libraries  ForceJS – SimpleOauth + REST toolkit without dependency  ForceTK – Salesforce REST API Toolkit  Nforce – node.js a REST API wrapper  ngForce – Visualforce Remoting integration in AngularJS  JSForce
  • 101.
    Lab 4: Usingthe REST APIs  Create a consumer app hosted outside Salesforce
  • 102.
    Windows Users After installingNode.js: 1. Add c:Program FilesNodejs to your path or Run "C:Program FilesNodejsnpm" install 2. Create an "npm" directory in C:Users[yourname]AppdataRoaming
  • 103.
  • 104.
    What are StaticResources?  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)
  • 105.
  • 106.
    Visualforce and HTMLPage 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>
  • 107.
    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')}"/>
  • 108.
    Controlling HTML PageGeneration  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="…">
  • 109.
    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>
  • 110.
    Lab 5: StaticResources  Host single page application in Visualforce page
  • 111.
  • 112.
    What is aCanvas 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.)
  • 113.
    Use Cases  InternalApp  Third-Party / Partner App  External systems with web facade
  • 114.
    Where Can ItBe Integrated?  Publisher  Page Layouts  Visualforce Pages  Tabs  Mobile Cards
  • 115.
  • 116.
    Transparent Authentication  Whenloading 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
  • 117.
    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; });
  • 118.
    Lab 6: Canvas Deploy Node.js web app to Heroku  Integrate app in Contact page layout
  • 119.
  • 120.
    Unit Testing  Codeto 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
  • 121.
    Anatomy of aTest 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 } }
  • 122.
    Create Temporary Data Datetimenow = 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;
  • 123.
    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());
  • 124.
  • 125.
    Lab 7: UnitTesting  Write the TestDoubleBooking class  Run the test
  • 126.
  • 127.
    What's a Batch? Long-running process that runs without manual intervention  Started programmatically
  • 128.
    Defining a BatchJob 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 } }
  • 129.
    Running the BatchJob 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);
  • 130.
    What's Scheduled Job? Unattended background program execution  Occurs at a specified time  Optionally repeated at a specified interval
  • 131.
    Defining a ScheduledJob 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); } }
  • 132.
    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);
  • 133.
    Scheduling the Job(using Clicks)
  • 134.
  • 135.
    Lab 8: Batchingand Scheduling  Write the SendReminderEmail class  Run the batch
  • 136.
    Next Steps inYour Developer Journey  http://developer.salesforce.com  Developer Forums  TrailHead  Webinars and Videos  Events  These slides are at http://slidesha.re/14DG6RA
  • 137.
    Survey Your feedback iscrucial to the success of our workshops. Thank you! http://bit.ly/ATL115

Editor's Notes

  • #11 This workshop covers the programmatic side, but before you start coding, it's always a good idea to ask yourself if what you are about to code can't be done declaratively. i.e Do I need to write that trigger, or can the same thing be done using a workflow?
  • #13 They should create a brand new DE org if they have not done so recently. They should not use a Trial, Sandbox or Production org. Emphasize our DE orgs are free and do not expire (they are not product trials)
  • #18 To model a many-to-many relationship you need to introduce a new object, called junction object. We call it Session_Speaker because it joins sessions and speakers. It may be useful to think about it as the "Booking" or "Assignment" object. To model the many-to-many relationship, you then define a one-to-many relationship between Session and Session_Speaker, and then between Speaker and Session_Speaker.
  • #87 Google Maps