SlideShare ist ein Scribd-Unternehmen logo
1 von 34
Downloaden Sie, um offline zu lesen
Lightning Connect Custom
Adapters
Connecting Anything with Salesforce
​ Lawrence McAlpin
​ Principal Member of Technical Staff
​ lmcalpin@salesforce.com
​ @lmcalpin
​ 
​ 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 any
litigation, risks associated with completed and any 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-K for the most recent fiscal year and in our quarterly report on Form 10-Q for the most recent fiscal quarter.
These 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.
Safe Harbor
Agenda
​  Background on External Data Sources
​  Custom Adapter Framework Overview
​  Demo
​  Provider Implementation
​  Connection Implementation
​  Pagination
​  Search
​  DML
​  Q&A
Background
●  Simplifies integration with
external systems
●  No magic
○  data is still remote
●  Ideal for use cases:
○  data is infrequently
accessed (such as
archival data)
○  you do not want to present
stale data
○  single point of truth
External Data Sources
• Data must be in a format we understand
▪  OData v2
▪  OData v4
▪  Salesforce
• Apex Custom Adapter Framework
▪  write your own!
• Data must be accessible to Salesforce
Custom Adapter Framework
Allows you to write your own Lightning Connect adapters
Custom Adapter Framework
●  Standard Governor limits apply
●  No limit to the number of Apex custom adapter classes you can define
●  Need Lightning Connect license to configure an External Data Source to use the
custom adapter
Demo
Custom Adapter Framework
●  DataSource.Provider
o  describes the capabilities of the external data source
o  creates the Connection class
●  DataSource.Connection
o  called whenever you import the metadata
o  called when you execute SOQL, SOSL, DML or equivalent UI interactions
DataSource.Provider
global class DummyDataSourceProvider extends DataSource.Provider {
override global List<DataSource.Capability> getCapabilities() {
List<DataSource.Capability> capabilities = new List<DataSource.Capability>();
capabilities.add(DataSource.Capability.ROW_QUERY);
capabilities.add(DataSource.Capability.SEARCH);
return capabilities;
}
override global List<DataSource.AuthenticationCapability> getAuthenticationCapabilities() {
List<DataSource.AuthenticationCapability> capabilities = new
List<DataSource.AuthenticationCapability>();
capabilities.add(DataSource.AuthenticationCapability.ANONYMOUS);
return capabilities;
}
override global DataSource.Connection getConnection(DataSource.ConnectionParams connectionParams) {
return new DummyDataSourceConnection(connectionParams);
}
}
DataSource.Provider
override global List<DataSource.Capability> getCapabilities()
​  ROW_QUERY
​  ROW_CREATE
​  ROW_UPDATE
​  ROW_DELETE
​  SEARCH
​  REQUIRE_ENDPOINT
​  REQUIRE_HTTPS
​  QUERY_TOTAL_SIZE
​  QUERY_PAGINATION_SERVER_DRIVEN
DataSource.Provider
getAuthenticationCapabilities
ANONYMOUS
BASIC
CERTIFICATE
OAUTH
DataSource.Provider
override global DataSource.Connection getConnection(DataSource.ConnectionParams connectionParams) {
return new DummyDataSourceConnection(connectionParams);
}
ConnectionParams properties
String username
String password
String oauthToken
AuthenticationProtocol protocol
String endpoint
String repository
IdentityType principalType
String certificateName
	
  
Callouts
Data may be retrieved using HTTP or Web service callouts
●  Authentication must be handled manually
o  throw OAuthTokenExpiredException to refresh the stored access token
o  all callout endpoints need to be registered in Remote Site Settings
HttpRequest req = new HttpRequest();
req.setEndpoint('http://www.wherever.com');
req.setMethod('GET');
if (protocol == DataSource.AuthenticationProtocol.PASSWORD) {
String username = connectionParams.username;
String password = connectionParams.password;
Blob headerValue = Blob.valueOf(username + ':' + password);
String authorizationHeader = 'BASIC ' + EncodingUtil.base64Encode(headerValue);
req.setHeader('Authorization', authorizationHeader);
} else if (protocol == DataSource.AuthenticationProtocol.OAUTH) {
req.setHeader('Authorization', 'Bearer ' + connectionParams.oauthToken);
}
Http http = new Http();
HTTPResponse res = http.send(req);
if (res.getStatusCode() == 401)
throw new OAuthTokenExpiredException();
Callouts with Named Credentials
Named Credentials are more flexible
but require additional setup
●  no direct access to credentials
●  no need to add to Remote Site
Settings
HttpRequest req = new HttpRequest();
req.setEndpoint(‘callout:test’);
req.setMethod('GET');
Http http = new Http();
HTTPResponse res = http.send(req);
Callouts with Named Credentials
Merge fields {!$CREDENTIAL.xxx}
●  USERNAME
●  PASSWORD
●  OAUTHTOKEN
●  AUTHORIZATIONMETHOD (BASIC, OAUTH)
●  AUTHORIZATIONHEADERVALUE (Base64 encoded username+password or Oauth token)
●  OAUTHCONSUMERKEY
// Concur expects OAuth to prefix the access token, instead of Bearer
req.setHeader(‘Authorization’, ‘OAuth {!$Credential.OAuthToken}’);
// non-standard authentication
req.setHeader(‘X-Username’, ‘{!$Credential.UserName}’);
req.setHeader(‘X-Password’, ‘{!$Credential.Password}’);
// you can also use it in the body
req.setBody(‘Dear {!$Credential.UserName}, I am a Salesforce Prince and as a Prince of Salesforce I
naturally own a metric crap ton of RSUs. If you send me 10,000 of teh bitcoins now I will deliver my
stock to you as it vests which wil be totes winwin.’);
DataSource.Connection
override global List<DataSource.Table> sync()
enumerates the list of Tables that this data source knows about
override global DataSource.TableResult query(DataSource.QueryContext c)
called when executing SOQL or visiting the List or Details pages in the UI
override global List<DataSource.TableResult> search(DataSource.SearchContext c)
called when executing SOSL or using the search functions in the UI
override global List<DataSource.UpsertResult> upsertRows(DataSource.UpsertContext c)
called when executing insert or update DML; also called when editing a record in the UI
override global List<DataSource.DeleteResult> deleteRows(DataSource.DeleteContext c)
called when executing delete DML; also called when deleting a record in the UI
Sync - DataSource.Table
override global List<DataSource.Table> sync() {
List<DataSource.Table> tables = new List<DataSource.Table>();
List<DataSource.Column> columns;
columns = new List<DataSource.Column>();
// next slide...
tables.add(DataSource.Table.get('Looper', 'Name', columns));
return tables;
}
Sync - DataSource.Column
columns = new List<DataSource.Column>();
columns.add(DataSource.Column.text('ExternalId', 255));
columns.add(DataSource.Column.url('DisplayUrl'));
columns.add(DataSource.Column.text('Name', 255));
columns.add(DataSource.Column.number('NumberOfEmployees', 18, 0));
Query
override global DataSource.TableResult query(DataSource.QueryContext c) {
HttpRequest req = prepareCallout(c);
List<Map<String,Object>> rows = getData(req);
// don’t forget the standard fields, especially ExternalId
for (Map<String,Object> row : rows) {
row.put('ExternalId', row.get(‘key’));
row.put('DisplayUrl', connectionParams.url + ‘/record/’ +
row.get(‘key’));
rows.add(row);
}
return DataSource.TableResult.get(c,rows);
}
QueryContext properties
TableSelection tableSelection
Integer offset
Integer maxResults
TableSelection properties
string tableSelected
List<ColumnSelection> columnsSelected
Filter filter
List<Order> order
TableResult properties
boolean success
String errorMessage
String tableName
List<Map<String,Object>> rows
integer totalSize
String queryMoreToken
Query Filters
/** Compound types **/
NOT_,
AND_,
OR_,
private string getSoqlFilter(string query,
DataSource.Filter filter) {
if (filter == null) { return query; }
DataSource.FilterType type = filter.type;
List<Map<String,Object>> retainedRows = new
List<Map<String,Object>>();
if (type == DataSource.FilterType.NOT_) {
DataSource.Filter subfilter =
filter.subfilters.get(0);
return ‘NOT ‘ +
getSoqlFilterExpression(subfilter);
} else if (type == DataSource.FilterType.AND_) {
return join('AND', filter.subfilters);
} else if (type == DataSource.FilterType.OR_) {
return join('OR', filter.subfilters);
}
return getSoqlFilterExpression(filter);
}
/** Simple comparative types **/
EQUALS,
NOT_EQUALS,
LESS_THAN,
GREATER_THAN,
private string getSoqlFilterExpression(DataSource.Filter filter) {
string op;
string columnName = filter.columnName;
object expectedValue = filter.columnValue;
if (filter.type == DataSource.FilterType.EQUALS) {
op = '=';
} else if (filter.type == DataSource.FilterType.NOT_EQUALS) {
op = '<>';
} else if (filter.type == DataSource.FilterType.LESS_THAN) {
op = '<';
} else if (filter.type == DataSource.FilterType.GREATER_THAN) {
op = '>';
} else if (filter.type == DataSource.FilterType.LESS_THAN_OR_EQUAL_TO) {
op = '<=';
} else if (filter.type == DataSource.FilterType.GREATER_THAN_OR_EQUAL_TO) {
op = '>=';
} else if (filter.type == DataSource.FilterType.STARTS_WITH) {
return mapColumnName(columnName) + ' LIKE '' + String.valueOf(expectedValue) + '%
'';
} else if (filter.type == DataSource.FilterType.ENDS_WITH) {
return mapColumnName(columnName) + ' LIKE '%' + String.valueOf(expectedValue) +
''';
} else {
throwException('DF15SpeakerWasLazyException: unimplemented filter type' +
filter.type);
}
return mapColumnName(columnName) + ' ' + op + ' ' + wrapValue(expectedValue);
}
LESS_THAN_OR_EQUAL_TO,
GREATER_THAN_OR_EQUAL_TO,
STARTS_WITH,
ENDS_WITH,
CONTAINS,
LIKE_
QueryMore
​  Can’t return all results in a single batch!
​  Not all external data sources handle pagination the same way
•  page number
•  token
•  limit, offset
​  Three strategies to handle pagination:
•  client driven, known total size
•  client driven, unknown total size
•  server driven
​  Driven by comabination of capabilities:
•  QUERY_TOTAL_SIZE
•  QUERY_SERVER_DRIVEN_PAGINATION
QueryMore - Client Driven, Known Total Size
​  Provider class declares QUERY_TOTAL_SIZE
​  /services/data/v35.0/query?q=SELECT...FROM+Xds__x
​  query
•  QueryContext maxResults = 1000
•  TableResult should have 1000 records as requested!!!
​  API call returns
{
"totalSize" => 1500,
"done" => false,
"nextRecordsUrl" => "/services/data/v35.0/query/01gxx000000B4WAAA0-1000",
"records" => [ … 1000 RECORDS … ]
}
​  queryMore call to /services/data/v35.0/query/xxx
​  query
•  QueryContext maxResults = 1000, and offset = 1000
•  TableResult should have 500 records
​  API call returns
{
"totalSize" => 1500,
"done" => true,
"records" => [ … 500 RECORDS … ]
}
QueryMore - Client Driven, Unknown Query Result Size
​  Default strategy used when provider does not support QUERY_TOTAL_SIZE or QUERY_SERVER_DRIVEN_PAGINATION
​  /services/data/v35.0/query?q=SELECT...FROM+Xds__x
​  query
•  QueryContext maxResults = 1001
•  TableResult should return 1001 records as requested!!!
​  SFDC API call returns
{
"totalSize" => -1,
"done" => false,
"nextRecordsUrl" => "/services/data/v35.0/query/01gxx000000B4WAAA0-1000",
"records" => [ … 1000 RECORDS … ]
}
​  queryMore call to /services/data/v35.0/query/xxx
​  query
•  QueryContext maxResults = 1001, and offset = 1000
•  TableResult should have 500 records
​  API call returns
{
"totalSize" => 1500,
"done" => true,
"records" => [ … 500 RECORDS … ]
}
QueryMore - Server Driven
​  Provider class declares QUERY_SERVER_DRIVEN_PAGINATION
​  /services/data/v35.0/query?q=SELECT...FROM+Xds__x
​  query
•  QueryContext maxResults = 0
•  TableResult should have however many records you want
•  TableResult must provide a queryMoreToken
​  API call returns the following if queryMoreToken is not null
{
"totalSize" => -1 or 1500, # depends on QUERY_TOTAL_SIZE support
"done" => false,
"nextRecordsUrl" => "/services/data/v35.0/query/01gxx000000B4WAAA0-1000",
"records" => [ … ??? RECORDS … ]
}
​  queryMore call to /services/data/v35.0/query/xxx
​  query
•  QueryContext queryMoreToken will be set to the token previously supplied
•  TableResult should have however many records you want
​  API call returns the following when queryMoreToken is null
{
"totalSize" => 1500,
"done" => true,
"records" => [ … ??? RECORDS … ]
}
Search
●  SOSL and Search UI operations invoke the search method on your Connection class
●  Multiple tables for a single connector may be searched in a single call
●  Display URL is intended to point to the search results in the external system
​ SearchContext properties
​ List<TableSelection> tableSelections
​ String searchPhrase
global static List<DataSource.TableResult> search(SearchContext c) {
List<DataSource.TableResult> results = new List<DataSource.TableResult>();
for (DataSource.TableSelection tableSelection : c.tableSelections) {
QueryContext ctx = new QueryContext();
ctx.tableSelection = tableSelection;
Table table = c.getTableMetadata(ctx.tableSelection);
tableSelection.filter = new Filter(FilterType.CONTAINS, ctx.tableSelection.tableSelected,
table.nameColumn, c.searchPhrase);
results.add(query(ctx));
}
return results;
}
Search
Inserts, Updates, Deletes
Requires DML capabilities in DataSource.Provider
●  ROW_CREATE
●  ROW_UPDATE
●  ROW_DELETE
Requires ID mapping
Requires Allow Create, Edit, and Delete selection on External Data Source
Insert, Updates
override global List<DataSource.UpsertResult> upsertRows(DataSource.UpsertContext c) {
List<DataSource.UpsertResult> results = new List<DataSource.UpsertResult>();
List<Map<String,Object>> rows = c.rows;
for (Map<String,Object> row : rows) {
String externalId = String.valueOf(row.get('ExternalId'));
// insert or update record in the external system
boolean success = // insert or update record
if (success) {
results.add(DataSource.UpsertResult.success(id));
} else {
results.add(DataSource.UpsertResult.failure(id, 'An error occurred updating this record'));
}
}
return results;
}
UpsertContext properties
String tableSelected
List<Map<string,object>> rows
UpsertResult properties
Boolean success
String errorMessage
String externalId
Deletes
override global List<DataSource.DeleteResult> deleteRows(DataSource.DeleteContext c) {
Set<Id> externalIds = new Set<Id>();
List<DataSource.DeleteResult> results = new List<DataSource.DeleteResult>();
for (String externalId : c.externalIds) {
boolean success = // delete record in external system
if (result.success) {
results.add(DataSource.DeleteResult.success(id));
} else {
results.add(DataSource.DeleteResult.failure(id, 'An error occurred
updating this record'));
}
}
return results;
}
DeleteContext properties
String tableSelected
List<String> externalIds
DeleteResult properties
Boolean success
String errorMessage
String externalId
DML
●  New Database methods used for external objects (only)
○  insertAsync
○  updateAsync
○  deleteAsync
●  DML operations are asynchronous
●  call getAsyncResult later to get results
Order__x x = new Order__x();
Database.SaveResult locator = Database.insertAsync(x);
if (!locator.isSuccess() && locator.getAsyncLocator() != null) {
// save was queued up for execution, when the result is ready, do some additional processing
completeOrderCreation(asyncLocator);
}
// must be in another transaction!!!
@future
public void completeOrderCreation(String asyncLocator) {
Database.SaveResult sr = Database.getAsyncResult(asyncLocator);
if (sr.isSuccess()) { … }
}
DML Callbacks
●  Callbacks to handle post-save processing
global class XdsSaveCallback extends DataSource.AsyncSaveCallback {
virtual global void processSave(Database.SaveResult sr) {
if (sr.isSuccess()) { … }
}
}
XdsSaveCallback cb = new XdsSaveCallback();
Order__x x = new Order__x();
Database.insertAsync(x, cb);
DML Callbacks
●  Callbacks to handle post-delete processing
global class XdsDeleteCallback extends DataSource.AsyncDeleteCallback {
virtual global void processDelete(Database.DeleteResult dr) {}
}
XdsDeleteCallback cb = new XdsDeleteCallback();
Xds__x x = [SELECT Id FROM Xds__x WHERE ExternalId = ‘...’];
Database.deleteAsync(x, cb);
Lawrence McAlpinLawrence McAlpin
Principal Member of Technical Staff
lmcalpin@salesforce.com
@lmcalpin

Weitere ähnliche Inhalte

Was ist angesagt?

The Role of the Salesforce Administrator
The Role of the Salesforce Administrator The Role of the Salesforce Administrator
The Role of the Salesforce Administrator Ebsta Limited
 
15 Tips on Salesforce Data Migration - Naveen Gabrani & Jonathan Osgood
15 Tips on Salesforce Data Migration - Naveen Gabrani & Jonathan Osgood15 Tips on Salesforce Data Migration - Naveen Gabrani & Jonathan Osgood
15 Tips on Salesforce Data Migration - Naveen Gabrani & Jonathan OsgoodSalesforce Admins
 
An introduction to Salesforce
An introduction to SalesforceAn introduction to Salesforce
An introduction to Salesforcevaluebound
 
Lightning web components
Lightning web components Lightning web components
Lightning web components Cloud Analogy
 
What Is Salesforce? | Salesforce Training - What Does Salesforce Do? | Salesf...
What Is Salesforce? | Salesforce Training - What Does Salesforce Do? | Salesf...What Is Salesforce? | Salesforce Training - What Does Salesforce Do? | Salesf...
What Is Salesforce? | Salesforce Training - What Does Salesforce Do? | Salesf...Edureka!
 
Building Mobile Apps on Salesforce Platform with Mobile SDK
Building Mobile Apps on Salesforce Platform with Mobile SDKBuilding Mobile Apps on Salesforce Platform with Mobile SDK
Building Mobile Apps on Salesforce Platform with Mobile SDKSalesforce Developers
 
Introduction to External Objects and the OData Connector
Introduction to External Objects and the OData ConnectorIntroduction to External Objects and the OData Connector
Introduction to External Objects and the OData ConnectorSalesforce Developers
 
Lightning Web Components- Ep 1 - Decorators, Life Cycle Hooks and Compositions
Lightning Web Components- Ep 1 - Decorators, Life Cycle Hooks and CompositionsLightning Web Components- Ep 1 - Decorators, Life Cycle Hooks and Compositions
Lightning Web Components- Ep 1 - Decorators, Life Cycle Hooks and CompositionsNishant Singh Panwar
 
Single Sign-On for APEX apps (Important: latest version on edocr!)
Single Sign-On for APEX apps (Important: latest version on edocr!)Single Sign-On for APEX apps (Important: latest version on edocr!)
Single Sign-On for APEX apps (Important: latest version on edocr!)Niels de Bruijn
 
Understanding Multitenancy and the Architecture of the Salesforce Platform
Understanding Multitenancy and the Architecture of the Salesforce PlatformUnderstanding Multitenancy and the Architecture of the Salesforce Platform
Understanding Multitenancy and the Architecture of the Salesforce PlatformSalesforce Developers
 
Introduction to lightning components
Introduction to lightning componentsIntroduction to lightning components
Introduction to lightning componentsMohith Shrivastava
 
Oracle APEX Introduction (release 18.1)
Oracle APEX Introduction (release 18.1)Oracle APEX Introduction (release 18.1)
Oracle APEX Introduction (release 18.1)Michael Hichwa
 
Ksplice - Keep your Database systems up to date with no downtime
Ksplice - Keep your Database systems up to date with no downtime Ksplice - Keep your Database systems up to date with no downtime
Ksplice - Keep your Database systems up to date with no downtime Luis Marques
 
Aura Framework Overview
Aura Framework OverviewAura Framework Overview
Aura Framework Overviewrajdeep
 
Salesforce Trailhead - what is it?
Salesforce Trailhead  - what is it?Salesforce Trailhead  - what is it?
Salesforce Trailhead - what is it?Roy Gilad
 
Keeping it Simple with Permission Sets
Keeping it Simple with Permission SetsKeeping it Simple with Permission Sets
Keeping it Simple with Permission SetsConfigero
 

Was ist angesagt? (20)

The Role of the Salesforce Administrator
The Role of the Salesforce Administrator The Role of the Salesforce Administrator
The Role of the Salesforce Administrator
 
15 Tips on Salesforce Data Migration - Naveen Gabrani & Jonathan Osgood
15 Tips on Salesforce Data Migration - Naveen Gabrani & Jonathan Osgood15 Tips on Salesforce Data Migration - Naveen Gabrani & Jonathan Osgood
15 Tips on Salesforce Data Migration - Naveen Gabrani & Jonathan Osgood
 
An introduction to Salesforce
An introduction to SalesforceAn introduction to Salesforce
An introduction to Salesforce
 
Em13c New Features- Two of Two
Em13c New Features- Two of TwoEm13c New Features- Two of Two
Em13c New Features- Two of Two
 
Lightning web components
Lightning web components Lightning web components
Lightning web components
 
Fiori Presentation
Fiori PresentationFiori Presentation
Fiori Presentation
 
Development Best Practices
Development Best PracticesDevelopment Best Practices
Development Best Practices
 
What Is Salesforce? | Salesforce Training - What Does Salesforce Do? | Salesf...
What Is Salesforce? | Salesforce Training - What Does Salesforce Do? | Salesf...What Is Salesforce? | Salesforce Training - What Does Salesforce Do? | Salesf...
What Is Salesforce? | Salesforce Training - What Does Salesforce Do? | Salesf...
 
Crunchy containers
Crunchy containersCrunchy containers
Crunchy containers
 
Building Mobile Apps on Salesforce Platform with Mobile SDK
Building Mobile Apps on Salesforce Platform with Mobile SDKBuilding Mobile Apps on Salesforce Platform with Mobile SDK
Building Mobile Apps on Salesforce Platform with Mobile SDK
 
Introduction to External Objects and the OData Connector
Introduction to External Objects and the OData ConnectorIntroduction to External Objects and the OData Connector
Introduction to External Objects and the OData Connector
 
Lightning Web Components- Ep 1 - Decorators, Life Cycle Hooks and Compositions
Lightning Web Components- Ep 1 - Decorators, Life Cycle Hooks and CompositionsLightning Web Components- Ep 1 - Decorators, Life Cycle Hooks and Compositions
Lightning Web Components- Ep 1 - Decorators, Life Cycle Hooks and Compositions
 
Single Sign-On for APEX apps (Important: latest version on edocr!)
Single Sign-On for APEX apps (Important: latest version on edocr!)Single Sign-On for APEX apps (Important: latest version on edocr!)
Single Sign-On for APEX apps (Important: latest version on edocr!)
 
Understanding Multitenancy and the Architecture of the Salesforce Platform
Understanding Multitenancy and the Architecture of the Salesforce PlatformUnderstanding Multitenancy and the Architecture of the Salesforce Platform
Understanding Multitenancy and the Architecture of the Salesforce Platform
 
Introduction to lightning components
Introduction to lightning componentsIntroduction to lightning components
Introduction to lightning components
 
Oracle APEX Introduction (release 18.1)
Oracle APEX Introduction (release 18.1)Oracle APEX Introduction (release 18.1)
Oracle APEX Introduction (release 18.1)
 
Ksplice - Keep your Database systems up to date with no downtime
Ksplice - Keep your Database systems up to date with no downtime Ksplice - Keep your Database systems up to date with no downtime
Ksplice - Keep your Database systems up to date with no downtime
 
Aura Framework Overview
Aura Framework OverviewAura Framework Overview
Aura Framework Overview
 
Salesforce Trailhead - what is it?
Salesforce Trailhead  - what is it?Salesforce Trailhead  - what is it?
Salesforce Trailhead - what is it?
 
Keeping it Simple with Permission Sets
Keeping it Simple with Permission SetsKeeping it Simple with Permission Sets
Keeping it Simple with Permission Sets
 

Andere mochten auch

Lightning Out: Components for the Rest of the World
Lightning Out: Components for the Rest of the WorldLightning Out: Components for the Rest of the World
Lightning Out: Components for the Rest of the WorldSalesforce Developers
 
Access External Data in Real-time with Lightning Connect
Access External Data in Real-time with Lightning ConnectAccess External Data in Real-time with Lightning Connect
Access External Data in Real-time with Lightning ConnectSalesforce Developers
 
Lightning strikes twice- SEDreamin
Lightning strikes twice- SEDreaminLightning strikes twice- SEDreamin
Lightning strikes twice- SEDreaminMohith Shrivastava
 
Secure Salesforce: Lightning Components Best Practices
Secure Salesforce: Lightning Components Best PracticesSecure Salesforce: Lightning Components Best Practices
Secure Salesforce: Lightning Components Best PracticesSalesforce Developers
 
Sap integration salesforce_presentation
Sap integration salesforce_presentationSap integration salesforce_presentation
Sap integration salesforce_presentationSalesforce Deutschland
 
Real-time SQL Access to Your Salesforce.com Data Using Progress Data Direct
Real-time SQL Access to Your Salesforce.com Data Using Progress Data DirectReal-time SQL Access to Your Salesforce.com Data Using Progress Data Direct
Real-time SQL Access to Your Salesforce.com Data Using Progress Data DirectSalesforce Developers
 
Introduction to Analytics Cloud
Introduction to Analytics CloudIntroduction to Analytics Cloud
Introduction to Analytics CloudMohith Shrivastava
 
Apex Connector for Lightning Connect: Make Anything a Salesforce Object
Apex Connector for Lightning Connect: Make Anything a Salesforce ObjectApex Connector for Lightning Connect: Make Anything a Salesforce Object
Apex Connector for Lightning Connect: Make Anything a Salesforce ObjectSalesforce Developers
 
Go Faster with Process Builder
Go Faster with Process BuilderGo Faster with Process Builder
Go Faster with Process Builderandyinthecloud
 
Force.com Canvas in the Publisher and Chatter Feed
Force.com Canvas in the Publisher and Chatter FeedForce.com Canvas in the Publisher and Chatter Feed
Force.com Canvas in the Publisher and Chatter FeedSalesforce Developers
 
Building strong foundations apex enterprise patterns
Building strong foundations apex enterprise patternsBuilding strong foundations apex enterprise patterns
Building strong foundations apex enterprise patternsandyinthecloud
 
Salesforce World Tour 2016 : Lightning Out : Components on any Platform
Salesforce World Tour 2016 : Lightning Out : Components on any PlatformSalesforce World Tour 2016 : Lightning Out : Components on any Platform
Salesforce World Tour 2016 : Lightning Out : Components on any Platformandyinthecloud
 
SAP Integration White Paper
SAP Integration White PaperSAP Integration White Paper
SAP Integration White PaperSaleem Rauf
 
Salesforce.com Org Migration Overview
Salesforce.com Org Migration OverviewSalesforce.com Org Migration Overview
Salesforce.com Org Migration OverviewShell Black
 
Multiorg Collaboration Using Salesforce S2S
Multiorg Collaboration Using Salesforce S2SMultiorg Collaboration Using Salesforce S2S
Multiorg Collaboration Using Salesforce S2SMayur Shintre
 
Dreamforce14 Multi Org Collaboration Architecture
Dreamforce14  Multi Org Collaboration ArchitectureDreamforce14  Multi Org Collaboration Architecture
Dreamforce14 Multi Org Collaboration ArchitectureRichard Clark
 
Continuous Deployment: The Dirty Details
Continuous Deployment: The Dirty DetailsContinuous Deployment: The Dirty Details
Continuous Deployment: The Dirty DetailsMike Brittain
 
SAP Marketing Runs Hybris Marketing By Andreas Starke
SAP Marketing Runs Hybris Marketing By Andreas StarkeSAP Marketing Runs Hybris Marketing By Andreas Starke
SAP Marketing Runs Hybris Marketing By Andreas StarkeMarTech Conference
 
Digital Transformation: Thinking Beyond CRM
Digital Transformation: Thinking Beyond CRMDigital Transformation: Thinking Beyond CRM
Digital Transformation: Thinking Beyond CRMSAP Customer Experience
 

Andere mochten auch (20)

Lightning Out: Components for the Rest of the World
Lightning Out: Components for the Rest of the WorldLightning Out: Components for the Rest of the World
Lightning Out: Components for the Rest of the World
 
Access External Data in Real-time with Lightning Connect
Access External Data in Real-time with Lightning ConnectAccess External Data in Real-time with Lightning Connect
Access External Data in Real-time with Lightning Connect
 
Lightning Connect: Lessons Learned
Lightning Connect: Lessons LearnedLightning Connect: Lessons Learned
Lightning Connect: Lessons Learned
 
Lightning strikes twice- SEDreamin
Lightning strikes twice- SEDreaminLightning strikes twice- SEDreamin
Lightning strikes twice- SEDreamin
 
Secure Salesforce: Lightning Components Best Practices
Secure Salesforce: Lightning Components Best PracticesSecure Salesforce: Lightning Components Best Practices
Secure Salesforce: Lightning Components Best Practices
 
Sap integration salesforce_presentation
Sap integration salesforce_presentationSap integration salesforce_presentation
Sap integration salesforce_presentation
 
Real-time SQL Access to Your Salesforce.com Data Using Progress Data Direct
Real-time SQL Access to Your Salesforce.com Data Using Progress Data DirectReal-time SQL Access to Your Salesforce.com Data Using Progress Data Direct
Real-time SQL Access to Your Salesforce.com Data Using Progress Data Direct
 
Introduction to Analytics Cloud
Introduction to Analytics CloudIntroduction to Analytics Cloud
Introduction to Analytics Cloud
 
Apex Connector for Lightning Connect: Make Anything a Salesforce Object
Apex Connector for Lightning Connect: Make Anything a Salesforce ObjectApex Connector for Lightning Connect: Make Anything a Salesforce Object
Apex Connector for Lightning Connect: Make Anything a Salesforce Object
 
Go Faster with Process Builder
Go Faster with Process BuilderGo Faster with Process Builder
Go Faster with Process Builder
 
Force.com Canvas in the Publisher and Chatter Feed
Force.com Canvas in the Publisher and Chatter FeedForce.com Canvas in the Publisher and Chatter Feed
Force.com Canvas in the Publisher and Chatter Feed
 
Building strong foundations apex enterprise patterns
Building strong foundations apex enterprise patternsBuilding strong foundations apex enterprise patterns
Building strong foundations apex enterprise patterns
 
Salesforce World Tour 2016 : Lightning Out : Components on any Platform
Salesforce World Tour 2016 : Lightning Out : Components on any PlatformSalesforce World Tour 2016 : Lightning Out : Components on any Platform
Salesforce World Tour 2016 : Lightning Out : Components on any Platform
 
SAP Integration White Paper
SAP Integration White PaperSAP Integration White Paper
SAP Integration White Paper
 
Salesforce.com Org Migration Overview
Salesforce.com Org Migration OverviewSalesforce.com Org Migration Overview
Salesforce.com Org Migration Overview
 
Multiorg Collaboration Using Salesforce S2S
Multiorg Collaboration Using Salesforce S2SMultiorg Collaboration Using Salesforce S2S
Multiorg Collaboration Using Salesforce S2S
 
Dreamforce14 Multi Org Collaboration Architecture
Dreamforce14  Multi Org Collaboration ArchitectureDreamforce14  Multi Org Collaboration Architecture
Dreamforce14 Multi Org Collaboration Architecture
 
Continuous Deployment: The Dirty Details
Continuous Deployment: The Dirty DetailsContinuous Deployment: The Dirty Details
Continuous Deployment: The Dirty Details
 
SAP Marketing Runs Hybris Marketing By Andreas Starke
SAP Marketing Runs Hybris Marketing By Andreas StarkeSAP Marketing Runs Hybris Marketing By Andreas Starke
SAP Marketing Runs Hybris Marketing By Andreas Starke
 
Digital Transformation: Thinking Beyond CRM
Digital Transformation: Thinking Beyond CRMDigital Transformation: Thinking Beyond CRM
Digital Transformation: Thinking Beyond CRM
 

Ähnlich wie Lightning Connect Custom Adapters: Connecting Anything with Salesforce

OData: A Standard API for Data Access
OData: A Standard API for Data AccessOData: A Standard API for Data Access
OData: A Standard API for Data AccessPat Patterson
 
Exploring SQL Server Azure Database Relationships Using Lightning Connect
Exploring SQL Server Azure Database Relationships Using Lightning ConnectExploring SQL Server Azure Database Relationships Using Lightning Connect
Exploring SQL Server Azure Database Relationships Using Lightning ConnectSalesforce Developers
 
Introduction to Developing Android Apps With the Salesforce Mobile SDK
Introduction to Developing Android Apps With the Salesforce Mobile SDKIntroduction to Developing Android Apps With the Salesforce Mobile SDK
Introduction to Developing Android Apps With the Salesforce Mobile SDKSalesforce Developers
 
Developing Offline Mobile Apps with the Salesforce.com Mobile SDK SmartStore,...
Developing Offline Mobile Apps with the Salesforce.com Mobile SDK SmartStore,...Developing Offline Mobile Apps with the Salesforce.com Mobile SDK SmartStore,...
Developing Offline Mobile Apps with the Salesforce.com Mobile SDK SmartStore,...Tom Gersic
 
Intro to AppExchange - Building Composite Apps
Intro to AppExchange - Building Composite AppsIntro to AppExchange - Building Composite Apps
Intro to AppExchange - Building Composite Appsdreamforce2006
 
ELEVATE Advanced Workshop
ELEVATE Advanced WorkshopELEVATE Advanced Workshop
ELEVATE Advanced WorkshopJoshua Birk
 
Quickly Create Data Sets for the Analytics Cloud
Quickly Create Data Sets for the Analytics CloudQuickly Create Data Sets for the Analytics Cloud
Quickly Create Data Sets for the Analytics CloudSalesforce Developers
 
Detroit ELEVATE Track 2
Detroit ELEVATE Track 2Detroit ELEVATE Track 2
Detroit ELEVATE Track 2Joshua Birk
 
Integrating Force.com with Heroku
Integrating Force.com with HerokuIntegrating Force.com with Heroku
Integrating Force.com with HerokuPat Patterson
 
Tour of Heroku + Salesforce Integration Methods
Tour of Heroku + Salesforce Integration MethodsTour of Heroku + Salesforce Integration Methods
Tour of Heroku + Salesforce Integration MethodsSalesforce Developers
 
Hca advanced developer workshop
Hca advanced developer workshopHca advanced developer workshop
Hca advanced developer workshopDavid Scruggs
 
Dreamforce 2017: Salesforce DX - an Admin's Perspective
Dreamforce 2017:  Salesforce DX - an Admin's PerspectiveDreamforce 2017:  Salesforce DX - an Admin's Perspective
Dreamforce 2017: Salesforce DX - an Admin's PerspectiveMike White
 
Introduction to the Wave Platform API
Introduction to the Wave Platform APIIntroduction to the Wave Platform API
Introduction to the Wave Platform APISalesforce Developers
 
Lightning components performance best practices
Lightning components performance best practicesLightning components performance best practices
Lightning components performance best practicesSalesforce Developers
 
How We Built AppExchange and our Communities on the App Cloud (Platform)
How We Built AppExchange and our Communities on the App Cloud (Platform)How We Built AppExchange and our Communities on the App Cloud (Platform)
How We Built AppExchange and our Communities on the App Cloud (Platform)Dreamforce
 
Understanding the Salesforce Architecture: How We Do the Magic We Do
Understanding the Salesforce Architecture: How We Do the Magic We DoUnderstanding the Salesforce Architecture: How We Do the Magic We Do
Understanding the Salesforce Architecture: How We Do the Magic We DoSalesforce Developers
 
Visualforce Hack for Junction Objects
Visualforce Hack for Junction ObjectsVisualforce Hack for Junction Objects
Visualforce Hack for Junction ObjectsRitesh Aswaney
 
Java Tech & Tools | Deploying Java & Play Framework Apps to the Cloud | Sande...
Java Tech & Tools | Deploying Java & Play Framework Apps to the Cloud | Sande...Java Tech & Tools | Deploying Java & Play Framework Apps to the Cloud | Sande...
Java Tech & Tools | Deploying Java & Play Framework Apps to the Cloud | Sande...JAX London
 
Salesforce1 Platform: Data Model, Relationships and Queries Webinar
Salesforce1 Platform: Data Model, Relationships and Queries WebinarSalesforce1 Platform: Data Model, Relationships and Queries Webinar
Salesforce1 Platform: Data Model, Relationships and Queries WebinarSalesforce Developers
 

Ähnlich wie Lightning Connect Custom Adapters: Connecting Anything with Salesforce (20)

OData: A Standard API for Data Access
OData: A Standard API for Data AccessOData: A Standard API for Data Access
OData: A Standard API for Data Access
 
Exploring SQL Server Azure Database Relationships Using Lightning Connect
Exploring SQL Server Azure Database Relationships Using Lightning ConnectExploring SQL Server Azure Database Relationships Using Lightning Connect
Exploring SQL Server Azure Database Relationships Using Lightning Connect
 
Introduction to Developing Android Apps With the Salesforce Mobile SDK
Introduction to Developing Android Apps With the Salesforce Mobile SDKIntroduction to Developing Android Apps With the Salesforce Mobile SDK
Introduction to Developing Android Apps With the Salesforce Mobile SDK
 
Developing Offline Mobile Apps with the Salesforce.com Mobile SDK SmartStore,...
Developing Offline Mobile Apps with the Salesforce.com Mobile SDK SmartStore,...Developing Offline Mobile Apps with the Salesforce.com Mobile SDK SmartStore,...
Developing Offline Mobile Apps with the Salesforce.com Mobile SDK SmartStore,...
 
Intro to AppExchange - Building Composite Apps
Intro to AppExchange - Building Composite AppsIntro to AppExchange - Building Composite Apps
Intro to AppExchange - Building Composite Apps
 
ELEVATE Advanced Workshop
ELEVATE Advanced WorkshopELEVATE Advanced Workshop
ELEVATE Advanced Workshop
 
Quickly Create Data Sets for the Analytics Cloud
Quickly Create Data Sets for the Analytics CloudQuickly Create Data Sets for the Analytics Cloud
Quickly Create Data Sets for the Analytics Cloud
 
Detroit ELEVATE Track 2
Detroit ELEVATE Track 2Detroit ELEVATE Track 2
Detroit ELEVATE Track 2
 
Integrating Force.com with Heroku
Integrating Force.com with HerokuIntegrating Force.com with Heroku
Integrating Force.com with Heroku
 
Tour of Heroku + Salesforce Integration Methods
Tour of Heroku + Salesforce Integration MethodsTour of Heroku + Salesforce Integration Methods
Tour of Heroku + Salesforce Integration Methods
 
Hca advanced developer workshop
Hca advanced developer workshopHca advanced developer workshop
Hca advanced developer workshop
 
Dreamforce 2017: Salesforce DX - an Admin's Perspective
Dreamforce 2017:  Salesforce DX - an Admin's PerspectiveDreamforce 2017:  Salesforce DX - an Admin's Perspective
Dreamforce 2017: Salesforce DX - an Admin's Perspective
 
ELEVATE Paris
ELEVATE ParisELEVATE Paris
ELEVATE Paris
 
Introduction to the Wave Platform API
Introduction to the Wave Platform APIIntroduction to the Wave Platform API
Introduction to the Wave Platform API
 
Lightning components performance best practices
Lightning components performance best practicesLightning components performance best practices
Lightning components performance best practices
 
How We Built AppExchange and our Communities on the App Cloud (Platform)
How We Built AppExchange and our Communities on the App Cloud (Platform)How We Built AppExchange and our Communities on the App Cloud (Platform)
How We Built AppExchange and our Communities on the App Cloud (Platform)
 
Understanding the Salesforce Architecture: How We Do the Magic We Do
Understanding the Salesforce Architecture: How We Do the Magic We DoUnderstanding the Salesforce Architecture: How We Do the Magic We Do
Understanding the Salesforce Architecture: How We Do the Magic We Do
 
Visualforce Hack for Junction Objects
Visualforce Hack for Junction ObjectsVisualforce Hack for Junction Objects
Visualforce Hack for Junction Objects
 
Java Tech & Tools | Deploying Java & Play Framework Apps to the Cloud | Sande...
Java Tech & Tools | Deploying Java & Play Framework Apps to the Cloud | Sande...Java Tech & Tools | Deploying Java & Play Framework Apps to the Cloud | Sande...
Java Tech & Tools | Deploying Java & Play Framework Apps to the Cloud | Sande...
 
Salesforce1 Platform: Data Model, Relationships and Queries Webinar
Salesforce1 Platform: Data Model, Relationships and Queries WebinarSalesforce1 Platform: Data Model, Relationships and Queries Webinar
Salesforce1 Platform: Data Model, Relationships and Queries Webinar
 

Mehr von Salesforce Developers

Sample Gallery: Reference Code and Best Practices for Salesforce Developers
Sample Gallery: Reference Code and Best Practices for Salesforce DevelopersSample Gallery: Reference Code and Best Practices for Salesforce Developers
Sample Gallery: Reference Code and Best Practices for Salesforce DevelopersSalesforce Developers
 
Maximizing Salesforce Lightning Experience and Lightning Component Performance
Maximizing Salesforce Lightning Experience and Lightning Component PerformanceMaximizing Salesforce Lightning Experience and Lightning Component Performance
Maximizing Salesforce Lightning Experience and Lightning Component PerformanceSalesforce Developers
 
Local development with Open Source Base Components
Local development with Open Source Base ComponentsLocal development with Open Source Base Components
Local development with Open Source Base ComponentsSalesforce Developers
 
TrailheaDX India : Developer Highlights
TrailheaDX India : Developer HighlightsTrailheaDX India : Developer Highlights
TrailheaDX India : Developer HighlightsSalesforce Developers
 
Why developers shouldn’t miss TrailheaDX India
Why developers shouldn’t miss TrailheaDX IndiaWhy developers shouldn’t miss TrailheaDX India
Why developers shouldn’t miss TrailheaDX IndiaSalesforce Developers
 
CodeLive: Build Lightning Web Components faster with Local Development
CodeLive: Build Lightning Web Components faster with Local DevelopmentCodeLive: Build Lightning Web Components faster with Local Development
CodeLive: Build Lightning Web Components faster with Local DevelopmentSalesforce Developers
 
CodeLive: Converting Aura Components to Lightning Web Components
CodeLive: Converting Aura Components to Lightning Web ComponentsCodeLive: Converting Aura Components to Lightning Web Components
CodeLive: Converting Aura Components to Lightning Web ComponentsSalesforce Developers
 
Enterprise-grade UI with open source Lightning Web Components
Enterprise-grade UI with open source Lightning Web ComponentsEnterprise-grade UI with open source Lightning Web Components
Enterprise-grade UI with open source Lightning Web ComponentsSalesforce Developers
 
TrailheaDX and Summer '19: Developer Highlights
TrailheaDX and Summer '19: Developer HighlightsTrailheaDX and Summer '19: Developer Highlights
TrailheaDX and Summer '19: Developer HighlightsSalesforce Developers
 
Lightning web components - Episode 4 : Security and Testing
Lightning web components  - Episode 4 : Security and TestingLightning web components  - Episode 4 : Security and Testing
Lightning web components - Episode 4 : Security and TestingSalesforce Developers
 
LWC Episode 3- Component Communication and Aura Interoperability
LWC Episode 3- Component Communication and Aura InteroperabilityLWC Episode 3- Component Communication and Aura Interoperability
LWC Episode 3- Component Communication and Aura InteroperabilitySalesforce Developers
 
Lightning web components episode 2- work with salesforce data
Lightning web components   episode 2- work with salesforce dataLightning web components   episode 2- work with salesforce data
Lightning web components episode 2- work with salesforce dataSalesforce Developers
 
Migrating CPQ to Advanced Calculator and JSQCP
Migrating CPQ to Advanced Calculator and JSQCPMigrating CPQ to Advanced Calculator and JSQCP
Migrating CPQ to Advanced Calculator and JSQCPSalesforce Developers
 
Scale with Large Data Volumes and Big Objects in Salesforce
Scale with Large Data Volumes and Big Objects in SalesforceScale with Large Data Volumes and Big Objects in Salesforce
Scale with Large Data Volumes and Big Objects in SalesforceSalesforce Developers
 
Replicate Salesforce Data in Real Time with Change Data Capture
Replicate Salesforce Data in Real Time with Change Data CaptureReplicate Salesforce Data in Real Time with Change Data Capture
Replicate Salesforce Data in Real Time with Change Data CaptureSalesforce Developers
 
Modern Development with Salesforce DX
Modern Development with Salesforce DXModern Development with Salesforce DX
Modern Development with Salesforce DXSalesforce Developers
 
Integrate CMS Content Into Lightning Communities with CMS Connect
Integrate CMS Content Into Lightning Communities with CMS ConnectIntegrate CMS Content Into Lightning Communities with CMS Connect
Integrate CMS Content Into Lightning Communities with CMS ConnectSalesforce Developers
 

Mehr von Salesforce Developers (20)

Sample Gallery: Reference Code and Best Practices for Salesforce Developers
Sample Gallery: Reference Code and Best Practices for Salesforce DevelopersSample Gallery: Reference Code and Best Practices for Salesforce Developers
Sample Gallery: Reference Code and Best Practices for Salesforce Developers
 
Maximizing Salesforce Lightning Experience and Lightning Component Performance
Maximizing Salesforce Lightning Experience and Lightning Component PerformanceMaximizing Salesforce Lightning Experience and Lightning Component Performance
Maximizing Salesforce Lightning Experience and Lightning Component Performance
 
Local development with Open Source Base Components
Local development with Open Source Base ComponentsLocal development with Open Source Base Components
Local development with Open Source Base Components
 
TrailheaDX India : Developer Highlights
TrailheaDX India : Developer HighlightsTrailheaDX India : Developer Highlights
TrailheaDX India : Developer Highlights
 
Why developers shouldn’t miss TrailheaDX India
Why developers shouldn’t miss TrailheaDX IndiaWhy developers shouldn’t miss TrailheaDX India
Why developers shouldn’t miss TrailheaDX India
 
CodeLive: Build Lightning Web Components faster with Local Development
CodeLive: Build Lightning Web Components faster with Local DevelopmentCodeLive: Build Lightning Web Components faster with Local Development
CodeLive: Build Lightning Web Components faster with Local Development
 
CodeLive: Converting Aura Components to Lightning Web Components
CodeLive: Converting Aura Components to Lightning Web ComponentsCodeLive: Converting Aura Components to Lightning Web Components
CodeLive: Converting Aura Components to Lightning Web Components
 
Enterprise-grade UI with open source Lightning Web Components
Enterprise-grade UI with open source Lightning Web ComponentsEnterprise-grade UI with open source Lightning Web Components
Enterprise-grade UI with open source Lightning Web Components
 
TrailheaDX and Summer '19: Developer Highlights
TrailheaDX and Summer '19: Developer HighlightsTrailheaDX and Summer '19: Developer Highlights
TrailheaDX and Summer '19: Developer Highlights
 
Live coding with LWC
Live coding with LWCLive coding with LWC
Live coding with LWC
 
Lightning web components - Episode 4 : Security and Testing
Lightning web components  - Episode 4 : Security and TestingLightning web components  - Episode 4 : Security and Testing
Lightning web components - Episode 4 : Security and Testing
 
LWC Episode 3- Component Communication and Aura Interoperability
LWC Episode 3- Component Communication and Aura InteroperabilityLWC Episode 3- Component Communication and Aura Interoperability
LWC Episode 3- Component Communication and Aura Interoperability
 
Lightning web components episode 2- work with salesforce data
Lightning web components   episode 2- work with salesforce dataLightning web components   episode 2- work with salesforce data
Lightning web components episode 2- work with salesforce data
 
Migrating CPQ to Advanced Calculator and JSQCP
Migrating CPQ to Advanced Calculator and JSQCPMigrating CPQ to Advanced Calculator and JSQCP
Migrating CPQ to Advanced Calculator and JSQCP
 
Scale with Large Data Volumes and Big Objects in Salesforce
Scale with Large Data Volumes and Big Objects in SalesforceScale with Large Data Volumes and Big Objects in Salesforce
Scale with Large Data Volumes and Big Objects in Salesforce
 
Replicate Salesforce Data in Real Time with Change Data Capture
Replicate Salesforce Data in Real Time with Change Data CaptureReplicate Salesforce Data in Real Time with Change Data Capture
Replicate Salesforce Data in Real Time with Change Data Capture
 
Modern Development with Salesforce DX
Modern Development with Salesforce DXModern Development with Salesforce DX
Modern Development with Salesforce DX
 
Get Into Lightning Flow Development
Get Into Lightning Flow DevelopmentGet Into Lightning Flow Development
Get Into Lightning Flow Development
 
Integrate CMS Content Into Lightning Communities with CMS Connect
Integrate CMS Content Into Lightning Communities with CMS ConnectIntegrate CMS Content Into Lightning Communities with CMS Connect
Integrate CMS Content Into Lightning Communities with CMS Connect
 
Introduction to MuleSoft
Introduction to MuleSoftIntroduction to MuleSoft
Introduction to MuleSoft
 

Kürzlich hochgeladen

Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesBoston Institute of Analytics
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessPixlogix Infotech
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 

Kürzlich hochgeladen (20)

Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 

Lightning Connect Custom Adapters: Connecting Anything with Salesforce

  • 1. Lightning Connect Custom Adapters Connecting Anything with Salesforce ​ Lawrence McAlpin ​ Principal Member of Technical Staff ​ lmcalpin@salesforce.com ​ @lmcalpin ​ 
  • 2. ​ 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 any litigation, risks associated with completed and any 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-K for the most recent fiscal year and in our quarterly report on Form 10-Q for the most recent fiscal quarter. These 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. Safe Harbor
  • 3. Agenda ​  Background on External Data Sources ​  Custom Adapter Framework Overview ​  Demo ​  Provider Implementation ​  Connection Implementation ​  Pagination ​  Search ​  DML ​  Q&A
  • 4. Background ●  Simplifies integration with external systems ●  No magic ○  data is still remote ●  Ideal for use cases: ○  data is infrequently accessed (such as archival data) ○  you do not want to present stale data ○  single point of truth
  • 5. External Data Sources • Data must be in a format we understand ▪  OData v2 ▪  OData v4 ▪  Salesforce • Apex Custom Adapter Framework ▪  write your own! • Data must be accessible to Salesforce
  • 6. Custom Adapter Framework Allows you to write your own Lightning Connect adapters
  • 7. Custom Adapter Framework ●  Standard Governor limits apply ●  No limit to the number of Apex custom adapter classes you can define ●  Need Lightning Connect license to configure an External Data Source to use the custom adapter
  • 9. Custom Adapter Framework ●  DataSource.Provider o  describes the capabilities of the external data source o  creates the Connection class ●  DataSource.Connection o  called whenever you import the metadata o  called when you execute SOQL, SOSL, DML or equivalent UI interactions
  • 10. DataSource.Provider global class DummyDataSourceProvider extends DataSource.Provider { override global List<DataSource.Capability> getCapabilities() { List<DataSource.Capability> capabilities = new List<DataSource.Capability>(); capabilities.add(DataSource.Capability.ROW_QUERY); capabilities.add(DataSource.Capability.SEARCH); return capabilities; } override global List<DataSource.AuthenticationCapability> getAuthenticationCapabilities() { List<DataSource.AuthenticationCapability> capabilities = new List<DataSource.AuthenticationCapability>(); capabilities.add(DataSource.AuthenticationCapability.ANONYMOUS); return capabilities; } override global DataSource.Connection getConnection(DataSource.ConnectionParams connectionParams) { return new DummyDataSourceConnection(connectionParams); } }
  • 11. DataSource.Provider override global List<DataSource.Capability> getCapabilities() ​  ROW_QUERY ​  ROW_CREATE ​  ROW_UPDATE ​  ROW_DELETE ​  SEARCH ​  REQUIRE_ENDPOINT ​  REQUIRE_HTTPS ​  QUERY_TOTAL_SIZE ​  QUERY_PAGINATION_SERVER_DRIVEN
  • 13. DataSource.Provider override global DataSource.Connection getConnection(DataSource.ConnectionParams connectionParams) { return new DummyDataSourceConnection(connectionParams); } ConnectionParams properties String username String password String oauthToken AuthenticationProtocol protocol String endpoint String repository IdentityType principalType String certificateName  
  • 14. Callouts Data may be retrieved using HTTP or Web service callouts ●  Authentication must be handled manually o  throw OAuthTokenExpiredException to refresh the stored access token o  all callout endpoints need to be registered in Remote Site Settings HttpRequest req = new HttpRequest(); req.setEndpoint('http://www.wherever.com'); req.setMethod('GET'); if (protocol == DataSource.AuthenticationProtocol.PASSWORD) { String username = connectionParams.username; String password = connectionParams.password; Blob headerValue = Blob.valueOf(username + ':' + password); String authorizationHeader = 'BASIC ' + EncodingUtil.base64Encode(headerValue); req.setHeader('Authorization', authorizationHeader); } else if (protocol == DataSource.AuthenticationProtocol.OAUTH) { req.setHeader('Authorization', 'Bearer ' + connectionParams.oauthToken); } Http http = new Http(); HTTPResponse res = http.send(req); if (res.getStatusCode() == 401) throw new OAuthTokenExpiredException();
  • 15. Callouts with Named Credentials Named Credentials are more flexible but require additional setup ●  no direct access to credentials ●  no need to add to Remote Site Settings HttpRequest req = new HttpRequest(); req.setEndpoint(‘callout:test’); req.setMethod('GET'); Http http = new Http(); HTTPResponse res = http.send(req);
  • 16. Callouts with Named Credentials Merge fields {!$CREDENTIAL.xxx} ●  USERNAME ●  PASSWORD ●  OAUTHTOKEN ●  AUTHORIZATIONMETHOD (BASIC, OAUTH) ●  AUTHORIZATIONHEADERVALUE (Base64 encoded username+password or Oauth token) ●  OAUTHCONSUMERKEY // Concur expects OAuth to prefix the access token, instead of Bearer req.setHeader(‘Authorization’, ‘OAuth {!$Credential.OAuthToken}’); // non-standard authentication req.setHeader(‘X-Username’, ‘{!$Credential.UserName}’); req.setHeader(‘X-Password’, ‘{!$Credential.Password}’); // you can also use it in the body req.setBody(‘Dear {!$Credential.UserName}, I am a Salesforce Prince and as a Prince of Salesforce I naturally own a metric crap ton of RSUs. If you send me 10,000 of teh bitcoins now I will deliver my stock to you as it vests which wil be totes winwin.’);
  • 17. DataSource.Connection override global List<DataSource.Table> sync() enumerates the list of Tables that this data source knows about override global DataSource.TableResult query(DataSource.QueryContext c) called when executing SOQL or visiting the List or Details pages in the UI override global List<DataSource.TableResult> search(DataSource.SearchContext c) called when executing SOSL or using the search functions in the UI override global List<DataSource.UpsertResult> upsertRows(DataSource.UpsertContext c) called when executing insert or update DML; also called when editing a record in the UI override global List<DataSource.DeleteResult> deleteRows(DataSource.DeleteContext c) called when executing delete DML; also called when deleting a record in the UI
  • 18. Sync - DataSource.Table override global List<DataSource.Table> sync() { List<DataSource.Table> tables = new List<DataSource.Table>(); List<DataSource.Column> columns; columns = new List<DataSource.Column>(); // next slide... tables.add(DataSource.Table.get('Looper', 'Name', columns)); return tables; }
  • 19. Sync - DataSource.Column columns = new List<DataSource.Column>(); columns.add(DataSource.Column.text('ExternalId', 255)); columns.add(DataSource.Column.url('DisplayUrl')); columns.add(DataSource.Column.text('Name', 255)); columns.add(DataSource.Column.number('NumberOfEmployees', 18, 0));
  • 20. Query override global DataSource.TableResult query(DataSource.QueryContext c) { HttpRequest req = prepareCallout(c); List<Map<String,Object>> rows = getData(req); // don’t forget the standard fields, especially ExternalId for (Map<String,Object> row : rows) { row.put('ExternalId', row.get(‘key’)); row.put('DisplayUrl', connectionParams.url + ‘/record/’ + row.get(‘key’)); rows.add(row); } return DataSource.TableResult.get(c,rows); } QueryContext properties TableSelection tableSelection Integer offset Integer maxResults TableSelection properties string tableSelected List<ColumnSelection> columnsSelected Filter filter List<Order> order TableResult properties boolean success String errorMessage String tableName List<Map<String,Object>> rows integer totalSize String queryMoreToken
  • 21. Query Filters /** Compound types **/ NOT_, AND_, OR_, private string getSoqlFilter(string query, DataSource.Filter filter) { if (filter == null) { return query; } DataSource.FilterType type = filter.type; List<Map<String,Object>> retainedRows = new List<Map<String,Object>>(); if (type == DataSource.FilterType.NOT_) { DataSource.Filter subfilter = filter.subfilters.get(0); return ‘NOT ‘ + getSoqlFilterExpression(subfilter); } else if (type == DataSource.FilterType.AND_) { return join('AND', filter.subfilters); } else if (type == DataSource.FilterType.OR_) { return join('OR', filter.subfilters); } return getSoqlFilterExpression(filter); } /** Simple comparative types **/ EQUALS, NOT_EQUALS, LESS_THAN, GREATER_THAN, private string getSoqlFilterExpression(DataSource.Filter filter) { string op; string columnName = filter.columnName; object expectedValue = filter.columnValue; if (filter.type == DataSource.FilterType.EQUALS) { op = '='; } else if (filter.type == DataSource.FilterType.NOT_EQUALS) { op = '<>'; } else if (filter.type == DataSource.FilterType.LESS_THAN) { op = '<'; } else if (filter.type == DataSource.FilterType.GREATER_THAN) { op = '>'; } else if (filter.type == DataSource.FilterType.LESS_THAN_OR_EQUAL_TO) { op = '<='; } else if (filter.type == DataSource.FilterType.GREATER_THAN_OR_EQUAL_TO) { op = '>='; } else if (filter.type == DataSource.FilterType.STARTS_WITH) { return mapColumnName(columnName) + ' LIKE '' + String.valueOf(expectedValue) + '% ''; } else if (filter.type == DataSource.FilterType.ENDS_WITH) { return mapColumnName(columnName) + ' LIKE '%' + String.valueOf(expectedValue) + '''; } else { throwException('DF15SpeakerWasLazyException: unimplemented filter type' + filter.type); } return mapColumnName(columnName) + ' ' + op + ' ' + wrapValue(expectedValue); } LESS_THAN_OR_EQUAL_TO, GREATER_THAN_OR_EQUAL_TO, STARTS_WITH, ENDS_WITH, CONTAINS, LIKE_
  • 22. QueryMore ​  Can’t return all results in a single batch! ​  Not all external data sources handle pagination the same way •  page number •  token •  limit, offset ​  Three strategies to handle pagination: •  client driven, known total size •  client driven, unknown total size •  server driven ​  Driven by comabination of capabilities: •  QUERY_TOTAL_SIZE •  QUERY_SERVER_DRIVEN_PAGINATION
  • 23. QueryMore - Client Driven, Known Total Size ​  Provider class declares QUERY_TOTAL_SIZE ​  /services/data/v35.0/query?q=SELECT...FROM+Xds__x ​  query •  QueryContext maxResults = 1000 •  TableResult should have 1000 records as requested!!! ​  API call returns { "totalSize" => 1500, "done" => false, "nextRecordsUrl" => "/services/data/v35.0/query/01gxx000000B4WAAA0-1000", "records" => [ … 1000 RECORDS … ] } ​  queryMore call to /services/data/v35.0/query/xxx ​  query •  QueryContext maxResults = 1000, and offset = 1000 •  TableResult should have 500 records ​  API call returns { "totalSize" => 1500, "done" => true, "records" => [ … 500 RECORDS … ] }
  • 24. QueryMore - Client Driven, Unknown Query Result Size ​  Default strategy used when provider does not support QUERY_TOTAL_SIZE or QUERY_SERVER_DRIVEN_PAGINATION ​  /services/data/v35.0/query?q=SELECT...FROM+Xds__x ​  query •  QueryContext maxResults = 1001 •  TableResult should return 1001 records as requested!!! ​  SFDC API call returns { "totalSize" => -1, "done" => false, "nextRecordsUrl" => "/services/data/v35.0/query/01gxx000000B4WAAA0-1000", "records" => [ … 1000 RECORDS … ] } ​  queryMore call to /services/data/v35.0/query/xxx ​  query •  QueryContext maxResults = 1001, and offset = 1000 •  TableResult should have 500 records ​  API call returns { "totalSize" => 1500, "done" => true, "records" => [ … 500 RECORDS … ] }
  • 25. QueryMore - Server Driven ​  Provider class declares QUERY_SERVER_DRIVEN_PAGINATION ​  /services/data/v35.0/query?q=SELECT...FROM+Xds__x ​  query •  QueryContext maxResults = 0 •  TableResult should have however many records you want •  TableResult must provide a queryMoreToken ​  API call returns the following if queryMoreToken is not null { "totalSize" => -1 or 1500, # depends on QUERY_TOTAL_SIZE support "done" => false, "nextRecordsUrl" => "/services/data/v35.0/query/01gxx000000B4WAAA0-1000", "records" => [ … ??? RECORDS … ] } ​  queryMore call to /services/data/v35.0/query/xxx ​  query •  QueryContext queryMoreToken will be set to the token previously supplied •  TableResult should have however many records you want ​  API call returns the following when queryMoreToken is null { "totalSize" => 1500, "done" => true, "records" => [ … ??? RECORDS … ] }
  • 26. Search ●  SOSL and Search UI operations invoke the search method on your Connection class ●  Multiple tables for a single connector may be searched in a single call ●  Display URL is intended to point to the search results in the external system
  • 27. ​ SearchContext properties ​ List<TableSelection> tableSelections ​ String searchPhrase global static List<DataSource.TableResult> search(SearchContext c) { List<DataSource.TableResult> results = new List<DataSource.TableResult>(); for (DataSource.TableSelection tableSelection : c.tableSelections) { QueryContext ctx = new QueryContext(); ctx.tableSelection = tableSelection; Table table = c.getTableMetadata(ctx.tableSelection); tableSelection.filter = new Filter(FilterType.CONTAINS, ctx.tableSelection.tableSelected, table.nameColumn, c.searchPhrase); results.add(query(ctx)); } return results; } Search
  • 28. Inserts, Updates, Deletes Requires DML capabilities in DataSource.Provider ●  ROW_CREATE ●  ROW_UPDATE ●  ROW_DELETE Requires ID mapping Requires Allow Create, Edit, and Delete selection on External Data Source
  • 29. Insert, Updates override global List<DataSource.UpsertResult> upsertRows(DataSource.UpsertContext c) { List<DataSource.UpsertResult> results = new List<DataSource.UpsertResult>(); List<Map<String,Object>> rows = c.rows; for (Map<String,Object> row : rows) { String externalId = String.valueOf(row.get('ExternalId')); // insert or update record in the external system boolean success = // insert or update record if (success) { results.add(DataSource.UpsertResult.success(id)); } else { results.add(DataSource.UpsertResult.failure(id, 'An error occurred updating this record')); } } return results; } UpsertContext properties String tableSelected List<Map<string,object>> rows UpsertResult properties Boolean success String errorMessage String externalId
  • 30. Deletes override global List<DataSource.DeleteResult> deleteRows(DataSource.DeleteContext c) { Set<Id> externalIds = new Set<Id>(); List<DataSource.DeleteResult> results = new List<DataSource.DeleteResult>(); for (String externalId : c.externalIds) { boolean success = // delete record in external system if (result.success) { results.add(DataSource.DeleteResult.success(id)); } else { results.add(DataSource.DeleteResult.failure(id, 'An error occurred updating this record')); } } return results; } DeleteContext properties String tableSelected List<String> externalIds DeleteResult properties Boolean success String errorMessage String externalId
  • 31. DML ●  New Database methods used for external objects (only) ○  insertAsync ○  updateAsync ○  deleteAsync ●  DML operations are asynchronous ●  call getAsyncResult later to get results Order__x x = new Order__x(); Database.SaveResult locator = Database.insertAsync(x); if (!locator.isSuccess() && locator.getAsyncLocator() != null) { // save was queued up for execution, when the result is ready, do some additional processing completeOrderCreation(asyncLocator); } // must be in another transaction!!! @future public void completeOrderCreation(String asyncLocator) { Database.SaveResult sr = Database.getAsyncResult(asyncLocator); if (sr.isSuccess()) { … } }
  • 32. DML Callbacks ●  Callbacks to handle post-save processing global class XdsSaveCallback extends DataSource.AsyncSaveCallback { virtual global void processSave(Database.SaveResult sr) { if (sr.isSuccess()) { … } } } XdsSaveCallback cb = new XdsSaveCallback(); Order__x x = new Order__x(); Database.insertAsync(x, cb);
  • 33. DML Callbacks ●  Callbacks to handle post-delete processing global class XdsDeleteCallback extends DataSource.AsyncDeleteCallback { virtual global void processDelete(Database.DeleteResult dr) {} } XdsDeleteCallback cb = new XdsDeleteCallback(); Xds__x x = [SELECT Id FROM Xds__x WHERE ExternalId = ‘...’]; Database.deleteAsync(x, cb);
  • 34. Lawrence McAlpinLawrence McAlpin Principal Member of Technical Staff lmcalpin@salesforce.com @lmcalpin