SlideShare a Scribd company logo
Beyond Custom Metadata Types
Avrom Roy-Faderman
Principal Member of Techincal Staff
Salesforce App Cloud
aroyfaderman@salesforce.com
@aroyfaderman
The Vision for “Platform on the Platform” in Force.com
Haripriya Murthy
Senior Member of Techincal Staff
Salesforce App Cloud
hmurthy@salesforce.com
@haripriyamurthy
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
CRM Apps ISV Apps IT Apps
The “Standard” Force.com Platform
App Cloud
Customer
The Salesforce Advantage
IT Apps
The “Platform on the Platform” Vision
App Cloud
CRM Apps ISV Apps IT Apps
Customer
IT AppsISV Apps
ISV Platform IT Platform
The <Your Company Name> Advantage
RemoteSiteSetting
ValidationRule
CustomObjectTranslation
PermissionSet
<Many more examples>
Standard Metadata Types Custom Metadata Types
The Story So Far…
ApiMapping
StockPointRule
InternationalVatRule
AclRule
<Whatever you want>
Instances are:
• Packageable/Upgradeable
• Deployable (change set/MD API)
• Free to access (via Describe)
• Salesforce writes the code that “makes them go”
Standard Metadata Types Custom Metadata Types
The Story So Far…
Instances are:
• Packageable/Upgradeable
• Deployable (change set/MD API)
• Free to access (via SOQL)
• You write the code that “makes them go”
The Vision for the Future
Demo: Coming… Now
• For everyone: Create Custom Metadata Types and Records in the Setup UI
• For ISVs: Control Field Editability and Record Visibility
Metadata Relationships
Dynamic Triggers
• With pseudocode walkthrough
Apex DDL
• With pseudocode walkthrough
Custom Datatypes
Summary/Roadmap/Q&A
And the Agenda for Today
Haripriya Murthy
Senior Member of the Technical Staff, Salesforce App Cloud
Demo
Coming… now (Winter 2016)
Metadata Relationships
Integrate your types into a unified declarative platform
RollupOverLookup__mdt
ParentObject__c: MD Rel
ParentField__c: MD Rel
SummarizedObject__c: MD Rel
LookupField__c: MD Rel
FieldToSummarize__c: MD Rel
RollupOperation__c: Picklist
Active__c: Checkbox
Description__c: LTA
Metadata relationships to SObjects
Triggerable SObject Types
RollupOverLookup__mdt
ParentObject__c: MD Rel
ParentField__c: MD Rel
SummarizedObject__c: MD
RelLookupField__c: MD Rel
LookupField__c: MD Rel
FieldToSummarize__c: MD Rel
RollupOperation__c: Picklist
Active__c: Checkbox
Description__c: LTA
Metadata relationships to SObjects
Triggerable SObject Types
ParentObject__c ParentField__c SummarizedObject__c FieldToSummarize__c RollupOperation__c
Contact TotalOppValue__c Opportunity Amount SUM
JobListing__c TotalAppliedCandidates__c Candidate__c COUNT
Metadata relationships to other types
RollupFilter__mdt
FilterField__c: MD Rel
FilterOperation__c: Picklist
Value__c: String
Summary__c: MD Rel
RollupOverLookup__mdt
ParentObject__c: MD Rel
ParentField__c: MD Rel
SummarizedObject__c: MD
RelLookupField__c: MD Rel
LookupField__c: MD Rel
FieldToSummarize__c: MD Rel
RollupOperation__c: Picklist
Active__c: Checkbox
Description__c: LTA
Metadata relationships to other types
FilterField__c FilterOperation__c Value__c Summary__c
Stage NOT EQUALS Closed Lost TotalAmountByContact__md
IsEmployee__c EQUALS False TotalApplicants__md
RollupFilter__mdt
FilterField__c: MD Rel
FilterOperation__c: Picklist
Value__c: String
Summary__c: MD Rel
RollupOverLookup__mdt
ParentObject__c: MD Rel
ParentField__c: MD Rel
SummarizedObject__c: MD Rel
LookupField__c: MD Rel
FieldToSummarize__c: MD Rel
RollupOperation__c: Picklist
Active__c: Checkbox
Description__c: LTA
RollupOverLookup__mdt
ParentObject__c: MD Rel
ParentField__c: MD Rel
SummarizedObject__c: MD Rel
LookupField__c: MD Rel
FieldToSummarize__c: MD Rel
RollupOperation__c: Picklist
Active__c: Checkbox
Description__c: LTA
Metadata relationships to Fields
Fields
Metadata relationships to other entities
Apex Classes
Custom
metadata
type
Permsets
Static resources
Creating a metadata relationship field
Metadata relationship in SOQL
Access the fields as is
select ParentObject__c, ParentField__c from RollupOverLookup__mdt where developerName = ‘OppExpectedRevenue’;
Metadata relationship in SOQL
Access the fields as is
select ParentObject__c, ParentField__c from RollupOverLookup__mdt where developerName = ‘OppExpectedRevenue’;
Traverse relationship from child
select ParentObject__r.Name from RollupOverLookup__mdt where developerName = ‘OppExpectedRevenue’;
Metadata relationship in SOQL
Access the fields as is
select ParentObject__c, ParentField__c from RollupOverLookup__mdt where developerName = ‘OppExpectedRevenue’;
Traverse relationship from child
select ParentObject__r.Name from RollupOverLookup__mdt where developerName = ‘OppExpectedRevenue’;
Filter using relationship
select ParentField__c from RollupOverLookup__mdt where developerName = ‘OppExpectedRevenue’ and
ParentObject__r.Name = ‘Opportunity’;
Dynamic Triggers
Customize the record save process
CustomField is of type Number?
• Non-numeric data rejected
CustomField is of type RollupSummary?
• On save of children, parents are updated
WorkflowRule exists on object?
• Should fire when the object saves and filter is
matched
Standard Metadata Types Custom Metadata Types
Metadata Should Affect the Save Process
InternationalVatRule applies?
• VAT should get added on save
“Rollup over Lookup” exists?
• On save of children, parents are updated
Object-Object mapping exists?
• When first object is inserted, transformed second
object should be inserted too
Step 1: Create a Custom Metadata Type
With a Relationship to Triggerable SObject Types
Triggerable SObject Types
RollupFilter__mdt
FilterField__c: MD Rel
FilterOperation__c: Picklist
Value__c: String
Summary__c: MD Rel
RollupOverLookup__mdt
ParentObject__c: MD Rel
ParentField__c: MD Rel
SummarizedObject__c: MD Rel
LookupField__c: MD Rel
FieldToSummarize__c: MD Rel
RollupOperation__c: Picklist
Active__c: Checkbox
Description__c: LTA
Step 2: Write a Dynamic Apex Trigger
over the Relationship
dynamic trigger RecalcRollupTrigger
over RollupOverLookup__mdt.SummarizedObject__c
(BEFORE INSERT, BEFORE UPDATE, BEFORE DELETE)
{
/* … */
}
You or an Admin Can Do This
Step 3: Populate the Custom Metadata Type
ParentObject__c ParentField__c SummarizedObject__c FieldToSummarize__c RollupOperation__c
Contact TotalOppValue__c Opportunity Amount SUM
JobListing__c TotalAppliedCandidates__c Candidate__c COUNT
FilterField__c FilterOperation__c Value__c Summary__c
Stage NOT EQUALS Closed Lost TotalAmountByContact__md
IsEmployee__c EQUALS False TotalApplicants__md
Runtime Example 1
Opportunities
End-user inserts some opportunities
RollupOverLookup__mdt records with
SummarizedObject__c = Opportunity found!
RecalcRollupTrigger executes before insert
• Trigger.sObjectType = Opportunity.sObjectType
• Trigger.customMetadata = [found records of RollupOverLookup__mdt]
Runtime Example 2
End-user inserts some contacts
No RollupOverLookup__mdt records with
SummarizedObject__c = Contact found!
RecalcRollupTrigger does not execute
Contacts
Pseudocode Example
dynamic trigger ReclalcRollupTrigger over RollupOverLookup__mdt.SummarizedObject__c
(BEFORE INSERT, BEFORE DELETE, BEFORE UPDATE) {
Schema.SObjectType thisObject = Trigger.sObjectType;
RollupOverLookup__mdt[] summariesOfThisObject = Trigger.customMetadata;
for (RollupOverLookup__mdt summary : summariesOfThisObject) {
RollupFilter__mdt[] filters = [SELECT FilterField__r.QualifiedApiName, Operation__c,
Value__c FROM RollupFilter__mdt WHERE Summary__c = summary.Id];
if (Trigger.isInsert) {
SObject[] matchingChildren = Trigger.new;
for (RollupFilter__mdt oneFilter : filters) {
matchingChildren = FilterUtil.filter(matchingChildren, oneFilter);
}
SObject[] parents = RollupUtil.getParents(
matchingChildren, summary.ParentObject__r.QualifiedApiName,
summary.LookupField__r.QualifiedApiName);
RollupUtil.adjustParents(
parents, summary.ParentField__r.QualifiedApiName, summary.RollupOperation__c,
matchingChildren, summary.FieldToSummarize__r.QualifiedApiName);
update parents;
}
…
}
}
Pseudocode Example
dynamic trigger ReclalcRollupTrigger over RollupOverLookup__mdt.SummarizedObject__c
(BEFORE INSERT, BEFORE DELETE, BEFORE UPDATE) {
Schema.SObjectType thisObject = Trigger.sObjectType;
RollupOverLookup__mdt[] summariesOfThisObject = Trigger.customMetadata;
for (RollupOverLookup__mdt summary : summariesOfThisObject) {
RollupFilter__mdt[] filters = [SELECT FilterField__r.QualifiedApiName, Operation__c,
Value__c FROM RollupFilter__mdt WHERE Summary__c = summary.Id];
if (Trigger.isInsert) {
SObject[] matchingChildren = Trigger.new;
for (RollupFilter__mdt oneFilter : filters) {
matchingChildren = FilterUtil.filter(matchingChildren, oneFilter);
}
SObject[] parents = RollupUtil.getParents(
matchingChildren, summary.ParentObject__r.QualifiedApiName,
summary.LookupField__r.QualifiedApiName);
RollupUtil.adjustParents(
parents, summary.ParentField__r.QualifiedApiName, summary.RollupOperation__c,
matchingChildren, summary.FieldToSummarize__r.QualifiedApiName);
update parents;
}
…
}
}
Pseudocode Example
dynamic trigger ReclalcRollupTrigger over RollupOverLookup__mdt.SummarizedObject__c
(BEFORE INSERT, BEFORE DELETE, BEFORE UPDATE) {
Schema.SObjectType thisObject = Trigger.sObjectType;
RollupOverLookup__mdt[] summariesOfThisObject = Trigger.customMetadata;
for (RollupOverLookup__mdt summary : summariesOfThisObject) {
RollupFilter__mdt[] filters = [SELECT FilterField__r.QualifiedApiName, Operation__c,
Value__c FROM RollupFilter__mdt WHERE Summary__c = summary.Id];
if (Trigger.isInsert) {
SObject[] matchingChildren = Trigger.new;
for (RollupFilter__mdt oneFilter : filters) {
matchingChildren = FilterUtil.filter(matchingChildren, oneFilter);
}
SObject[] parents = RollupUtil.getParents(
matchingChildren, summary.ParentObject__r.QualifiedApiName,
summary.LookupField__r.QualifiedApiName);
RollupUtil.adjustParents(
parents, summary.ParentField__r.QualifiedApiName, summary.RollupOperation__c,
matchingChildren, summary.FieldToSummarize__r.QualifiedApiName);
update parents;
}
…
}
Pseudocode Example
dynamic trigger ReclalcRollupTrigger over RollupOverLookup__mdt.SummarizedObject__c
(BEFORE INSERT, BEFORE DELETE, BEFORE UPDATE) {
Schema.SObjectType thisObject = Trigger.sObjectType;
RollupOverLookup__mdt[] summariesOfThisObject = Trigger.customMetadata;
for (RollupOverLookup__mdt summary : summariesOfThisObject) {
RollupFilter__mdt[] filters = [SELECT FilterField__r.QualifiedApiName, Operation__c,
Value__c FROM RollupFilter__mdt WHERE Summary__c = summary.Id];
if (Trigger.isInsert) {
SObject[] matchingChildren = Trigger.new;
for (RollupFilter__mdt oneFilter : filters) {
matchingChildren = FilterUtil.filter(matchingChildren, oneFilter);
}
SObject[] parents = RollupUtil.getParents(
matchingChildren, summary.ParentObject__r.QualifiedApiName,
summary.LookupField__r.QualifiedApiName);
RollupUtil.adjustParents(
parents, summary.ParentField__r.QualifiedApiName, summary.RollupOperation__c,
matchingChildren, summary.FieldToSummarize__r.QualifiedApiName);
update parents;
}
…
}
}
Pseudocode Example
dynamic trigger ReclalcRollupTrigger over RollupOverLookup__mdt.SummarizedObject__c
(BEFORE INSERT, BEFORE DELETE, BEFORE UPDATE) {
Schema.SObjectType thisObject = Trigger.sObjectType;
RollupOverLookup__mdt[] summariesOfThisObject = Trigger.customMetadata;
for (RollupOverLookup__mdt summary : summariesOfThisObject) {
RollupFilter__mdt[] filters = [SELECT FilterField__r.QualifiedApiName, Operation__c,
Value__c FROM RollupFilter__mdt WHERE Summary__c = summary.Id];
if (Trigger.isInsert) {
SObject[] matchingChildren = Trigger.new;
for (RollupFilter__mdt oneFilter : filters) {
matchingChildren = FilterUtil.filter(matchingChildren, oneFilter);
}
SObject[] parents = RollupUtil.getParents(
matchingChildren, summary.ParentObject__r.QualifiedApiName,
summary.LookupField__r.QualifiedApiName);
RollupUtil.adjustParents(
parents, summary.ParentField__r.QualifiedApiName, summary.RollupOperation__c,
matchingChildren, summary.FieldToSummarize__r.QualifiedApiName);
update parents;
}
…
}
}
• Lets the platform developer control the save process of Sobjects using your custom metadata types.
• Code written by the platform developer will be executed for entities that might not even exist at the
time the code was written.
• ISVs can package dynamic triggers and the triggers can be used to modify save process of the
customer org’s objects that use the platform built by the ISVs.
Dynamic triggers
Apex DDL
Set up metadata natively
Create metadata in native apex
• Fewer manual install procedures
• Easier custom tooling
• No callouts required
public void createRollupField(String devName, EntityDefinition parent, EntityDefinition child,
FieldDefinition summarized, FieldDefinition lookup,
PicklistValue op) {
MetadataContainer mdc = new MetadataContainer();
insert mdc;
FieldDefinition summarizingField = new FieldDefintion();
summarizingField.EntityId = parent.EntityId;
summarizingField.DeveloperName = devName;
…
mdc.addMember(summarizingField);
RollupOverLookup__mdt rollup = new RollupOverLookup__mdt();
rollup.ParentObject__c = parent.EntityId;
rollup.SummarizedObject__c = child.EntityId;
rollup.RollupOperation__c = op;
rollup.parentField__r = summarizingField;
…
mdc.addMember(rollup);
mdc.deploy();
}
Pseudocode Example
Pseudocode Example
public void createRollupField(String devName, EntityDefinition parent, EntityDefinition child,
FieldDefinition summarized, FieldDefinition lookup,
PicklistValue op) {
MetadataContainer mdc = new MetadataContainer();
insert mdc;
FieldDefinition summarizingField = new FieldDefintion();
summarizingField.EntityId = parent.EntityId;
summarizingField.DeveloperName = devName;
…
mdc.addMember(summarizingField);
RollupOverLookup__mdt rollup = new RollupOverLookup__mdt();
rollup.ParentObject__c = parent.EntityId;
rollup.ChildObject__c = child.EntityId;
rollup.RollupOperation__c = op;
rollup.parentField__r = summarizingField;
…
mdc.addMember(rollup);
mdc.deploy();
}
public void createRollupField(String devName, EntityDefinition parent, EntityDefinition child,
FieldDefinition summarized, FieldDefinition lookup,
PicklistValue op) {
MetadataContainer mdc = new MetadataContainer();
insert mdc;
FieldDefinition summarizingField = new FieldDefintion();
summarizingField.EntityId = parent.EntityId;
summarizingField.DeveloperName = devName;
…
mdc.addMember(summarizingField);
RollupOverLookup__mdt rollup = new RollupOverLookup__mdt();
rollup.ParentObject__c = parent.EntityId;
rollup.ChildObject__c = child.EntityId;
rollup.RollupOperation__c = op;
rollup.parentField__r = summarizingField;
…
mdc.addMember(rollup);
mdc.deploy();
}
Pseudocode Example
public void createRollupField(String devName, EntityDefinition parent, EntityDefinition child,
FieldDefinition summarized, FieldDefinition lookup,
PicklistValue op) {
MetadataContainer mdc = new MetadataContainer();
insert mdc;
FieldDefinition summarizingField = new FieldDefintion();
summarizingField.EntityId = parent.EntityId;
summarizingField.DeveloperName = devName;
…
mdc.addMember(summarizingField);
RollupOverLookup__mdt rollup = new RollupOverLookup__mdt();
rollup.ParentObject__c = parent.EntityId;
rollup.ChildObject__c = child.EntityId;
rollup.RollupOperation__c = op;
rollup.parentField__r = summarizingField;
…
mdc.addMember(rollup);
mdc.deploy();
}
Pseudocode Example
public void createRollupField(String devName, EntityDefinition parent, EntityDefinition child,
FieldDefinition summarized, FieldDefinition lookup,
PicklistValue op) {
MetadataContainer mdc = new MetadataContainer();
insert mdc;
FieldDefinition summarizingField = new FieldDefintion();
summarizingField.EntityId = parent.EntityId;
summarizingField.DeveloperName = devName;
…
mdc.addMember(summarizingField);
RollupOverLookup__mdt rollup = new RollupOverLookup__mdt();
rollup.ParentObject__c = parent.EntityId;
rollup.ChildObject__c = child.EntityId;
rollup.RollupOperation__c = op;
rollup.parentField__r = summarizingField;
…
mdc.addMember(rollup);
mdc.deploy();
}
Pseudocode Example
public void createRollupField(String devName, EntityDefinition parent, EntityDefinition child,
FieldDefinition summarized, FieldDefinition lookup,
PicklistValue op) {
MetadataContainer mdc = new MetadataContainer();
insert mdc;
FieldDefinition summarizingField = new FieldDefintion();
summarizingField.EntityId = parent.EntityId;
summarizingField.DeveloperName = devName;
…
mdc.addMember(summarizingField);
RollupOverLookup__mdt rollup = new RollupOverLookup__mdt();
rollup.ParentObject__c = parent.EntityId;
rollup.ChildObject__c = child.EntityId;
rollup.RollupOperation__c = op;
rollup.parentField__r = summarizingField;
…
mdc.addMember(rollup);
mdc.deploy();
}
Pseudocode Example
public void createRollupField(String devName, EntityDefinition parent, EntityDefinition child,
FieldDefinition summarized, FieldDefinition lookup,
PicklistValue op) {
MetadataContainer mdc = new MetadataContainer();
insert mdc;
FieldDefinition summarizingField = new FieldDefintion();
summarizingField.EntityId = parent.EntityId;
summarizingField.DeveloperName = devName;
…
mdc.addMember(summarizingField);
RollupOverLookup__mdt rollup = new RollupOverLookup__mdt();
rollup.ParentObject__c = parent.EntityId;
rollup.ChildObject__c = child.EntityId;
rollup.RollupOperation__c = op;
rollup.parentField__r = summarizingField;
…
mdc.addMember(rollup);
mdc.deploy();
}
Pseudocode Example
Avrom Roy-Faderman
Principal Member of the Technical Staff, Salesforce App Cloud
Custom Datatypes
Create your own meta-schema
Custom Datatypes
Compound and configurable
Custom datatype
Column
Column
Column
One or more columns of
standard datatypes
Custom metadata type
Custom Datatypes
Compound and configurable
Custom datatype
Column
Column
Column
Custom Field
DefinitionsMD Rel Field
Values of this field get
auto-populated with
fields of the custom
datatype
Custom metadata type
Custom Datatypes
Compound and configurable
Custom datatype
Column
Column
Column
MD Rel Field
Field
Field
Other fields here contain
additional metadata
relevant to fields of this
type
RollupOverLookup__mdt
Example Custom Datatype
RollupOverLookup
RollupOverLookup
Value__s Fields of type
RollupOverLookupParentField__c
SummarizedField__c
Operation__c
…
Creating a Field of the Custom Type
Summary and Roadmap
Our vision: Open up the platform to partners and customers the way the platform opens up apps
• Custom metadata types are a first step towards this, providing custom types of metadata with standard:
• SDLC
• Packaging
• Setup UI
• Fast runtime access
• More features on our roadmap
• Metadata relationships for type integration (plus other datatypes!)
• Customizable save process via dynamic triggers
• Custom tooling and automated setup via Apex DDL
• Custom datatypes for fields
• Even more stuff in the longer term!
Summary
Available now Spring ’16 Summer ’16 Winter ’17 Beyond
Metadata
Relationships
Apex DDL
Dynamic
Triggers
Custom
Datatypes
Extra-super-special safe harbor!
Roadmap
Pilot GA
Pilot GA
GA
Pilot GA
Share Your Feedback, and Win a GoPro!
3
Earn a GoPro prize entry for
each completed survey
Tap the bell to take a
survey2Enroll in a session1
Thank you

More Related Content

PDF
Manage Development in Your Org with Salesforce Governance Framework
PDF
Best Practices for Rolling Out New Functionality
PPTX
Classic vs. lightning
PDF
Business Process Mapping for Salesforce Admins
PPTX
COPADO - Plateforme de DEVOPS pour Salesforce
PPTX
Seamless Authentication with Force.com Canvas
PPTX
Salesforce sales cloud solutions
PDF
The Role of the Salesforce Administrator
Manage Development in Your Org with Salesforce Governance Framework
Best Practices for Rolling Out New Functionality
Classic vs. lightning
Business Process Mapping for Salesforce Admins
COPADO - Plateforme de DEVOPS pour Salesforce
Seamless Authentication with Force.com Canvas
Salesforce sales cloud solutions
The Role of the Salesforce Administrator

What's hot (20)

PDF
Understanding the Salesforce Architecture: How We Do the Magic We Do
PPTX
Sap integration salesforce_presentation
PPTX
Integration using Salesforce Canvas
PDF
Account planning.pptx
PPTX
Salesforce Integration Patterns
PPTX
Lessons from implementing Salesforce Industries / Vlocity in Insurance, Jiří ...
PDF
Performing a successful technical debt assessment in Salesforce
PPTX
What is Salesforce lighting explained
PDF
Salesforce crm and its cloud services ppt converted
PDF
Manage Salesforce Like a Pro with Governance
PDF
Planning Your Migration to the Lightning Experience
PDF
Drive Adoption of Salesforce at Your Company
PDF
Building a Center of Excellence for your Salesforce crm team
PDF
A comprehensive guide to Salesforce Org Strategy
PPTX
Salesforce CPQ by yuvaraj
PDF
Flow in Salesforce
PDF
How Marketing Cloud Latest Features Can Improve Your Campaign Performance
PPTX
An introduction to Salesforce
PPTX
Salesforce as a PaaS - Architecture of Force.com
PDF
einstein-cheatsheet.pdf
Understanding the Salesforce Architecture: How We Do the Magic We Do
Sap integration salesforce_presentation
Integration using Salesforce Canvas
Account planning.pptx
Salesforce Integration Patterns
Lessons from implementing Salesforce Industries / Vlocity in Insurance, Jiří ...
Performing a successful technical debt assessment in Salesforce
What is Salesforce lighting explained
Salesforce crm and its cloud services ppt converted
Manage Salesforce Like a Pro with Governance
Planning Your Migration to the Lightning Experience
Drive Adoption of Salesforce at Your Company
Building a Center of Excellence for your Salesforce crm team
A comprehensive guide to Salesforce Org Strategy
Salesforce CPQ by yuvaraj
Flow in Salesforce
How Marketing Cloud Latest Features Can Improve Your Campaign Performance
An introduction to Salesforce
Salesforce as a PaaS - Architecture of Force.com
einstein-cheatsheet.pdf
Ad

Similar to Beyond Custom Metadata Types (20)

PDF
ISV Monthly Tech Enablement (May 18, 2017)
PPTX
Custom Metadata Data Types
PPTX
Solving Complex Data Load Challenges
PDF
WT19: Metadata Magic: Maintain Code, Without the Code!
PPT
Salesforce1 Platform for programmers
PDF
Winter '20 Salesforce Release for Admins and Developers + New Salesforce Mobi...
PDF
Elevate london dec 2014.pptx
PDF
Diagramming Salesforce Solutions: Matthew Morris - Jacksonville Architects - ...
PPTX
Salesforce Dreamforce 2019-Announcements
PDF
ISV Monthly Tech Enablement (July 2017)
PDF
Best practices in using Salesforce Metadata API
PPTX
Dreamforce 2019 GG & Spring 20 release features - Halifax, Canada Community
PPTX
Route your triggers like a pro #DF18
PPTX
[MBF2] Plate-forme Salesforce par Peter Chittum
PDF
Use Custom Metadata Types for Easy ALM & Compliance for Your Custom Apps
PDF
Introduction to Force.com Webinar
PDF
Intro to Force.com Webinar presentation
PDF
Become a Superstar Admin with Custom Metadata Types
PPTX
Integrating with salesforce
PPTX
Salesforce Developer Group Toronto - Winter'19
ISV Monthly Tech Enablement (May 18, 2017)
Custom Metadata Data Types
Solving Complex Data Load Challenges
WT19: Metadata Magic: Maintain Code, Without the Code!
Salesforce1 Platform for programmers
Winter '20 Salesforce Release for Admins and Developers + New Salesforce Mobi...
Elevate london dec 2014.pptx
Diagramming Salesforce Solutions: Matthew Morris - Jacksonville Architects - ...
Salesforce Dreamforce 2019-Announcements
ISV Monthly Tech Enablement (July 2017)
Best practices in using Salesforce Metadata API
Dreamforce 2019 GG & Spring 20 release features - Halifax, Canada Community
Route your triggers like a pro #DF18
[MBF2] Plate-forme Salesforce par Peter Chittum
Use Custom Metadata Types for Easy ALM & Compliance for Your Custom Apps
Introduction to Force.com Webinar
Intro to Force.com Webinar presentation
Become a Superstar Admin with Custom Metadata Types
Integrating with salesforce
Salesforce Developer Group Toronto - Winter'19
Ad

More from Salesforce Developers (20)

PDF
Sample Gallery: Reference Code and Best Practices for Salesforce Developers
PDF
Maximizing Salesforce Lightning Experience and Lightning Component Performance
PDF
Local development with Open Source Base Components
PPTX
TrailheaDX India : Developer Highlights
PDF
Why developers shouldn’t miss TrailheaDX India
PPTX
CodeLive: Build Lightning Web Components faster with Local Development
PPTX
CodeLive: Converting Aura Components to Lightning Web Components
PPTX
Enterprise-grade UI with open source Lightning Web Components
PPTX
TrailheaDX and Summer '19: Developer Highlights
PDF
Live coding with LWC
PDF
Lightning web components - Episode 4 : Security and Testing
PDF
LWC Episode 3- Component Communication and Aura Interoperability
PDF
Lightning web components episode 2- work with salesforce data
PDF
Lightning web components - Episode 1 - An Introduction
PDF
Migrating CPQ to Advanced Calculator and JSQCP
PDF
Scale with Large Data Volumes and Big Objects in Salesforce
PDF
Replicate Salesforce Data in Real Time with Change Data Capture
PDF
Modern Development with Salesforce DX
PDF
Get Into Lightning Flow Development
PDF
Integrate CMS Content Into Lightning Communities with CMS Connect
Sample Gallery: Reference Code and Best Practices for Salesforce Developers
Maximizing Salesforce Lightning Experience and Lightning Component Performance
Local development with Open Source Base Components
TrailheaDX India : Developer Highlights
Why developers shouldn’t miss TrailheaDX India
CodeLive: Build Lightning Web Components faster with Local Development
CodeLive: Converting Aura Components to Lightning Web Components
Enterprise-grade UI with open source Lightning Web Components
TrailheaDX and Summer '19: Developer Highlights
Live coding with LWC
Lightning web components - Episode 4 : Security and Testing
LWC Episode 3- Component Communication and Aura Interoperability
Lightning web components episode 2- work with salesforce data
Lightning web components - Episode 1 - An Introduction
Migrating CPQ to Advanced Calculator and JSQCP
Scale with Large Data Volumes and Big Objects in Salesforce
Replicate Salesforce Data in Real Time with Change Data Capture
Modern Development with Salesforce DX
Get Into Lightning Flow Development
Integrate CMS Content Into Lightning Communities with CMS Connect

Recently uploaded (20)

PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
A comparative analysis of optical character recognition models for extracting...
PPTX
Machine Learning_overview_presentation.pptx
PPTX
A Presentation on Artificial Intelligence
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Assigned Numbers - 2025 - Bluetooth® Document
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PPTX
Big Data Technologies - Introduction.pptx
PDF
Approach and Philosophy of On baking technology
DOCX
The AUB Centre for AI in Media Proposal.docx
PPTX
Spectroscopy.pptx food analysis technology
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
Machine learning based COVID-19 study performance prediction
PDF
Electronic commerce courselecture one. Pdf
PDF
Empathic Computing: Creating Shared Understanding
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PPTX
MYSQL Presentation for SQL database connectivity
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
A comparative analysis of optical character recognition models for extracting...
Machine Learning_overview_presentation.pptx
A Presentation on Artificial Intelligence
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Mobile App Security Testing_ A Comprehensive Guide.pdf
Assigned Numbers - 2025 - Bluetooth® Document
Network Security Unit 5.pdf for BCA BBA.
Chapter 3 Spatial Domain Image Processing.pdf
Big Data Technologies - Introduction.pptx
Approach and Philosophy of On baking technology
The AUB Centre for AI in Media Proposal.docx
Spectroscopy.pptx food analysis technology
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Machine learning based COVID-19 study performance prediction
Electronic commerce courselecture one. Pdf
Empathic Computing: Creating Shared Understanding
Agricultural_Statistics_at_a_Glance_2022_0.pdf
MYSQL Presentation for SQL database connectivity

Beyond Custom Metadata Types

  • 1. Beyond Custom Metadata Types Avrom Roy-Faderman Principal Member of Techincal Staff Salesforce App Cloud aroyfaderman@salesforce.com @aroyfaderman The Vision for “Platform on the Platform” in Force.com Haripriya Murthy Senior Member of Techincal Staff Salesforce App Cloud hmurthy@salesforce.com @haripriyamurthy
  • 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. CRM Apps ISV Apps IT Apps The “Standard” Force.com Platform App Cloud Customer The Salesforce Advantage
  • 4. IT Apps The “Platform on the Platform” Vision App Cloud CRM Apps ISV Apps IT Apps Customer IT AppsISV Apps ISV Platform IT Platform The <Your Company Name> Advantage
  • 5. RemoteSiteSetting ValidationRule CustomObjectTranslation PermissionSet <Many more examples> Standard Metadata Types Custom Metadata Types The Story So Far… ApiMapping StockPointRule InternationalVatRule AclRule <Whatever you want>
  • 6. Instances are: • Packageable/Upgradeable • Deployable (change set/MD API) • Free to access (via Describe) • Salesforce writes the code that “makes them go” Standard Metadata Types Custom Metadata Types The Story So Far… Instances are: • Packageable/Upgradeable • Deployable (change set/MD API) • Free to access (via SOQL) • You write the code that “makes them go”
  • 7. The Vision for the Future Demo: Coming… Now • For everyone: Create Custom Metadata Types and Records in the Setup UI • For ISVs: Control Field Editability and Record Visibility Metadata Relationships Dynamic Triggers • With pseudocode walkthrough Apex DDL • With pseudocode walkthrough Custom Datatypes Summary/Roadmap/Q&A And the Agenda for Today
  • 8. Haripriya Murthy Senior Member of the Technical Staff, Salesforce App Cloud
  • 10. Metadata Relationships Integrate your types into a unified declarative platform
  • 11. RollupOverLookup__mdt ParentObject__c: MD Rel ParentField__c: MD Rel SummarizedObject__c: MD Rel LookupField__c: MD Rel FieldToSummarize__c: MD Rel RollupOperation__c: Picklist Active__c: Checkbox Description__c: LTA Metadata relationships to SObjects Triggerable SObject Types
  • 12. RollupOverLookup__mdt ParentObject__c: MD Rel ParentField__c: MD Rel SummarizedObject__c: MD RelLookupField__c: MD Rel LookupField__c: MD Rel FieldToSummarize__c: MD Rel RollupOperation__c: Picklist Active__c: Checkbox Description__c: LTA Metadata relationships to SObjects Triggerable SObject Types ParentObject__c ParentField__c SummarizedObject__c FieldToSummarize__c RollupOperation__c Contact TotalOppValue__c Opportunity Amount SUM JobListing__c TotalAppliedCandidates__c Candidate__c COUNT
  • 13. Metadata relationships to other types RollupFilter__mdt FilterField__c: MD Rel FilterOperation__c: Picklist Value__c: String Summary__c: MD Rel RollupOverLookup__mdt ParentObject__c: MD Rel ParentField__c: MD Rel SummarizedObject__c: MD RelLookupField__c: MD Rel LookupField__c: MD Rel FieldToSummarize__c: MD Rel RollupOperation__c: Picklist Active__c: Checkbox Description__c: LTA
  • 14. Metadata relationships to other types FilterField__c FilterOperation__c Value__c Summary__c Stage NOT EQUALS Closed Lost TotalAmountByContact__md IsEmployee__c EQUALS False TotalApplicants__md RollupFilter__mdt FilterField__c: MD Rel FilterOperation__c: Picklist Value__c: String Summary__c: MD Rel RollupOverLookup__mdt ParentObject__c: MD Rel ParentField__c: MD Rel SummarizedObject__c: MD Rel LookupField__c: MD Rel FieldToSummarize__c: MD Rel RollupOperation__c: Picklist Active__c: Checkbox Description__c: LTA
  • 15. RollupOverLookup__mdt ParentObject__c: MD Rel ParentField__c: MD Rel SummarizedObject__c: MD Rel LookupField__c: MD Rel FieldToSummarize__c: MD Rel RollupOperation__c: Picklist Active__c: Checkbox Description__c: LTA Metadata relationships to Fields Fields
  • 16. Metadata relationships to other entities Apex Classes Custom metadata type Permsets Static resources
  • 17. Creating a metadata relationship field
  • 18. Metadata relationship in SOQL Access the fields as is select ParentObject__c, ParentField__c from RollupOverLookup__mdt where developerName = ‘OppExpectedRevenue’;
  • 19. Metadata relationship in SOQL Access the fields as is select ParentObject__c, ParentField__c from RollupOverLookup__mdt where developerName = ‘OppExpectedRevenue’; Traverse relationship from child select ParentObject__r.Name from RollupOverLookup__mdt where developerName = ‘OppExpectedRevenue’;
  • 20. Metadata relationship in SOQL Access the fields as is select ParentObject__c, ParentField__c from RollupOverLookup__mdt where developerName = ‘OppExpectedRevenue’; Traverse relationship from child select ParentObject__r.Name from RollupOverLookup__mdt where developerName = ‘OppExpectedRevenue’; Filter using relationship select ParentField__c from RollupOverLookup__mdt where developerName = ‘OppExpectedRevenue’ and ParentObject__r.Name = ‘Opportunity’;
  • 21. Dynamic Triggers Customize the record save process
  • 22. CustomField is of type Number? • Non-numeric data rejected CustomField is of type RollupSummary? • On save of children, parents are updated WorkflowRule exists on object? • Should fire when the object saves and filter is matched Standard Metadata Types Custom Metadata Types Metadata Should Affect the Save Process InternationalVatRule applies? • VAT should get added on save “Rollup over Lookup” exists? • On save of children, parents are updated Object-Object mapping exists? • When first object is inserted, transformed second object should be inserted too
  • 23. Step 1: Create a Custom Metadata Type With a Relationship to Triggerable SObject Types Triggerable SObject Types RollupFilter__mdt FilterField__c: MD Rel FilterOperation__c: Picklist Value__c: String Summary__c: MD Rel RollupOverLookup__mdt ParentObject__c: MD Rel ParentField__c: MD Rel SummarizedObject__c: MD Rel LookupField__c: MD Rel FieldToSummarize__c: MD Rel RollupOperation__c: Picklist Active__c: Checkbox Description__c: LTA
  • 24. Step 2: Write a Dynamic Apex Trigger over the Relationship dynamic trigger RecalcRollupTrigger over RollupOverLookup__mdt.SummarizedObject__c (BEFORE INSERT, BEFORE UPDATE, BEFORE DELETE) { /* … */ }
  • 25. You or an Admin Can Do This Step 3: Populate the Custom Metadata Type ParentObject__c ParentField__c SummarizedObject__c FieldToSummarize__c RollupOperation__c Contact TotalOppValue__c Opportunity Amount SUM JobListing__c TotalAppliedCandidates__c Candidate__c COUNT FilterField__c FilterOperation__c Value__c Summary__c Stage NOT EQUALS Closed Lost TotalAmountByContact__md IsEmployee__c EQUALS False TotalApplicants__md
  • 26. Runtime Example 1 Opportunities End-user inserts some opportunities RollupOverLookup__mdt records with SummarizedObject__c = Opportunity found! RecalcRollupTrigger executes before insert • Trigger.sObjectType = Opportunity.sObjectType • Trigger.customMetadata = [found records of RollupOverLookup__mdt]
  • 27. Runtime Example 2 End-user inserts some contacts No RollupOverLookup__mdt records with SummarizedObject__c = Contact found! RecalcRollupTrigger does not execute Contacts
  • 28. Pseudocode Example dynamic trigger ReclalcRollupTrigger over RollupOverLookup__mdt.SummarizedObject__c (BEFORE INSERT, BEFORE DELETE, BEFORE UPDATE) { Schema.SObjectType thisObject = Trigger.sObjectType; RollupOverLookup__mdt[] summariesOfThisObject = Trigger.customMetadata; for (RollupOverLookup__mdt summary : summariesOfThisObject) { RollupFilter__mdt[] filters = [SELECT FilterField__r.QualifiedApiName, Operation__c, Value__c FROM RollupFilter__mdt WHERE Summary__c = summary.Id]; if (Trigger.isInsert) { SObject[] matchingChildren = Trigger.new; for (RollupFilter__mdt oneFilter : filters) { matchingChildren = FilterUtil.filter(matchingChildren, oneFilter); } SObject[] parents = RollupUtil.getParents( matchingChildren, summary.ParentObject__r.QualifiedApiName, summary.LookupField__r.QualifiedApiName); RollupUtil.adjustParents( parents, summary.ParentField__r.QualifiedApiName, summary.RollupOperation__c, matchingChildren, summary.FieldToSummarize__r.QualifiedApiName); update parents; } … } }
  • 29. Pseudocode Example dynamic trigger ReclalcRollupTrigger over RollupOverLookup__mdt.SummarizedObject__c (BEFORE INSERT, BEFORE DELETE, BEFORE UPDATE) { Schema.SObjectType thisObject = Trigger.sObjectType; RollupOverLookup__mdt[] summariesOfThisObject = Trigger.customMetadata; for (RollupOverLookup__mdt summary : summariesOfThisObject) { RollupFilter__mdt[] filters = [SELECT FilterField__r.QualifiedApiName, Operation__c, Value__c FROM RollupFilter__mdt WHERE Summary__c = summary.Id]; if (Trigger.isInsert) { SObject[] matchingChildren = Trigger.new; for (RollupFilter__mdt oneFilter : filters) { matchingChildren = FilterUtil.filter(matchingChildren, oneFilter); } SObject[] parents = RollupUtil.getParents( matchingChildren, summary.ParentObject__r.QualifiedApiName, summary.LookupField__r.QualifiedApiName); RollupUtil.adjustParents( parents, summary.ParentField__r.QualifiedApiName, summary.RollupOperation__c, matchingChildren, summary.FieldToSummarize__r.QualifiedApiName); update parents; } … } }
  • 30. Pseudocode Example dynamic trigger ReclalcRollupTrigger over RollupOverLookup__mdt.SummarizedObject__c (BEFORE INSERT, BEFORE DELETE, BEFORE UPDATE) { Schema.SObjectType thisObject = Trigger.sObjectType; RollupOverLookup__mdt[] summariesOfThisObject = Trigger.customMetadata; for (RollupOverLookup__mdt summary : summariesOfThisObject) { RollupFilter__mdt[] filters = [SELECT FilterField__r.QualifiedApiName, Operation__c, Value__c FROM RollupFilter__mdt WHERE Summary__c = summary.Id]; if (Trigger.isInsert) { SObject[] matchingChildren = Trigger.new; for (RollupFilter__mdt oneFilter : filters) { matchingChildren = FilterUtil.filter(matchingChildren, oneFilter); } SObject[] parents = RollupUtil.getParents( matchingChildren, summary.ParentObject__r.QualifiedApiName, summary.LookupField__r.QualifiedApiName); RollupUtil.adjustParents( parents, summary.ParentField__r.QualifiedApiName, summary.RollupOperation__c, matchingChildren, summary.FieldToSummarize__r.QualifiedApiName); update parents; } … }
  • 31. Pseudocode Example dynamic trigger ReclalcRollupTrigger over RollupOverLookup__mdt.SummarizedObject__c (BEFORE INSERT, BEFORE DELETE, BEFORE UPDATE) { Schema.SObjectType thisObject = Trigger.sObjectType; RollupOverLookup__mdt[] summariesOfThisObject = Trigger.customMetadata; for (RollupOverLookup__mdt summary : summariesOfThisObject) { RollupFilter__mdt[] filters = [SELECT FilterField__r.QualifiedApiName, Operation__c, Value__c FROM RollupFilter__mdt WHERE Summary__c = summary.Id]; if (Trigger.isInsert) { SObject[] matchingChildren = Trigger.new; for (RollupFilter__mdt oneFilter : filters) { matchingChildren = FilterUtil.filter(matchingChildren, oneFilter); } SObject[] parents = RollupUtil.getParents( matchingChildren, summary.ParentObject__r.QualifiedApiName, summary.LookupField__r.QualifiedApiName); RollupUtil.adjustParents( parents, summary.ParentField__r.QualifiedApiName, summary.RollupOperation__c, matchingChildren, summary.FieldToSummarize__r.QualifiedApiName); update parents; } … } }
  • 32. Pseudocode Example dynamic trigger ReclalcRollupTrigger over RollupOverLookup__mdt.SummarizedObject__c (BEFORE INSERT, BEFORE DELETE, BEFORE UPDATE) { Schema.SObjectType thisObject = Trigger.sObjectType; RollupOverLookup__mdt[] summariesOfThisObject = Trigger.customMetadata; for (RollupOverLookup__mdt summary : summariesOfThisObject) { RollupFilter__mdt[] filters = [SELECT FilterField__r.QualifiedApiName, Operation__c, Value__c FROM RollupFilter__mdt WHERE Summary__c = summary.Id]; if (Trigger.isInsert) { SObject[] matchingChildren = Trigger.new; for (RollupFilter__mdt oneFilter : filters) { matchingChildren = FilterUtil.filter(matchingChildren, oneFilter); } SObject[] parents = RollupUtil.getParents( matchingChildren, summary.ParentObject__r.QualifiedApiName, summary.LookupField__r.QualifiedApiName); RollupUtil.adjustParents( parents, summary.ParentField__r.QualifiedApiName, summary.RollupOperation__c, matchingChildren, summary.FieldToSummarize__r.QualifiedApiName); update parents; } … } }
  • 33. • Lets the platform developer control the save process of Sobjects using your custom metadata types. • Code written by the platform developer will be executed for entities that might not even exist at the time the code was written. • ISVs can package dynamic triggers and the triggers can be used to modify save process of the customer org’s objects that use the platform built by the ISVs. Dynamic triggers
  • 34. Apex DDL Set up metadata natively
  • 35. Create metadata in native apex • Fewer manual install procedures • Easier custom tooling • No callouts required
  • 36. public void createRollupField(String devName, EntityDefinition parent, EntityDefinition child, FieldDefinition summarized, FieldDefinition lookup, PicklistValue op) { MetadataContainer mdc = new MetadataContainer(); insert mdc; FieldDefinition summarizingField = new FieldDefintion(); summarizingField.EntityId = parent.EntityId; summarizingField.DeveloperName = devName; … mdc.addMember(summarizingField); RollupOverLookup__mdt rollup = new RollupOverLookup__mdt(); rollup.ParentObject__c = parent.EntityId; rollup.SummarizedObject__c = child.EntityId; rollup.RollupOperation__c = op; rollup.parentField__r = summarizingField; … mdc.addMember(rollup); mdc.deploy(); } Pseudocode Example
  • 37. Pseudocode Example public void createRollupField(String devName, EntityDefinition parent, EntityDefinition child, FieldDefinition summarized, FieldDefinition lookup, PicklistValue op) { MetadataContainer mdc = new MetadataContainer(); insert mdc; FieldDefinition summarizingField = new FieldDefintion(); summarizingField.EntityId = parent.EntityId; summarizingField.DeveloperName = devName; … mdc.addMember(summarizingField); RollupOverLookup__mdt rollup = new RollupOverLookup__mdt(); rollup.ParentObject__c = parent.EntityId; rollup.ChildObject__c = child.EntityId; rollup.RollupOperation__c = op; rollup.parentField__r = summarizingField; … mdc.addMember(rollup); mdc.deploy(); }
  • 38. public void createRollupField(String devName, EntityDefinition parent, EntityDefinition child, FieldDefinition summarized, FieldDefinition lookup, PicklistValue op) { MetadataContainer mdc = new MetadataContainer(); insert mdc; FieldDefinition summarizingField = new FieldDefintion(); summarizingField.EntityId = parent.EntityId; summarizingField.DeveloperName = devName; … mdc.addMember(summarizingField); RollupOverLookup__mdt rollup = new RollupOverLookup__mdt(); rollup.ParentObject__c = parent.EntityId; rollup.ChildObject__c = child.EntityId; rollup.RollupOperation__c = op; rollup.parentField__r = summarizingField; … mdc.addMember(rollup); mdc.deploy(); } Pseudocode Example
  • 39. public void createRollupField(String devName, EntityDefinition parent, EntityDefinition child, FieldDefinition summarized, FieldDefinition lookup, PicklistValue op) { MetadataContainer mdc = new MetadataContainer(); insert mdc; FieldDefinition summarizingField = new FieldDefintion(); summarizingField.EntityId = parent.EntityId; summarizingField.DeveloperName = devName; … mdc.addMember(summarizingField); RollupOverLookup__mdt rollup = new RollupOverLookup__mdt(); rollup.ParentObject__c = parent.EntityId; rollup.ChildObject__c = child.EntityId; rollup.RollupOperation__c = op; rollup.parentField__r = summarizingField; … mdc.addMember(rollup); mdc.deploy(); } Pseudocode Example
  • 40. public void createRollupField(String devName, EntityDefinition parent, EntityDefinition child, FieldDefinition summarized, FieldDefinition lookup, PicklistValue op) { MetadataContainer mdc = new MetadataContainer(); insert mdc; FieldDefinition summarizingField = new FieldDefintion(); summarizingField.EntityId = parent.EntityId; summarizingField.DeveloperName = devName; … mdc.addMember(summarizingField); RollupOverLookup__mdt rollup = new RollupOverLookup__mdt(); rollup.ParentObject__c = parent.EntityId; rollup.ChildObject__c = child.EntityId; rollup.RollupOperation__c = op; rollup.parentField__r = summarizingField; … mdc.addMember(rollup); mdc.deploy(); } Pseudocode Example
  • 41. public void createRollupField(String devName, EntityDefinition parent, EntityDefinition child, FieldDefinition summarized, FieldDefinition lookup, PicklistValue op) { MetadataContainer mdc = new MetadataContainer(); insert mdc; FieldDefinition summarizingField = new FieldDefintion(); summarizingField.EntityId = parent.EntityId; summarizingField.DeveloperName = devName; … mdc.addMember(summarizingField); RollupOverLookup__mdt rollup = new RollupOverLookup__mdt(); rollup.ParentObject__c = parent.EntityId; rollup.ChildObject__c = child.EntityId; rollup.RollupOperation__c = op; rollup.parentField__r = summarizingField; … mdc.addMember(rollup); mdc.deploy(); } Pseudocode Example
  • 42. public void createRollupField(String devName, EntityDefinition parent, EntityDefinition child, FieldDefinition summarized, FieldDefinition lookup, PicklistValue op) { MetadataContainer mdc = new MetadataContainer(); insert mdc; FieldDefinition summarizingField = new FieldDefintion(); summarizingField.EntityId = parent.EntityId; summarizingField.DeveloperName = devName; … mdc.addMember(summarizingField); RollupOverLookup__mdt rollup = new RollupOverLookup__mdt(); rollup.ParentObject__c = parent.EntityId; rollup.ChildObject__c = child.EntityId; rollup.RollupOperation__c = op; rollup.parentField__r = summarizingField; … mdc.addMember(rollup); mdc.deploy(); } Pseudocode Example
  • 43. Avrom Roy-Faderman Principal Member of the Technical Staff, Salesforce App Cloud
  • 44. Custom Datatypes Create your own meta-schema
  • 45. Custom Datatypes Compound and configurable Custom datatype Column Column Column One or more columns of standard datatypes
  • 46. Custom metadata type Custom Datatypes Compound and configurable Custom datatype Column Column Column Custom Field DefinitionsMD Rel Field Values of this field get auto-populated with fields of the custom datatype
  • 47. Custom metadata type Custom Datatypes Compound and configurable Custom datatype Column Column Column MD Rel Field Field Field Other fields here contain additional metadata relevant to fields of this type
  • 48. RollupOverLookup__mdt Example Custom Datatype RollupOverLookup RollupOverLookup Value__s Fields of type RollupOverLookupParentField__c SummarizedField__c Operation__c …
  • 49. Creating a Field of the Custom Type
  • 51. Our vision: Open up the platform to partners and customers the way the platform opens up apps • Custom metadata types are a first step towards this, providing custom types of metadata with standard: • SDLC • Packaging • Setup UI • Fast runtime access • More features on our roadmap • Metadata relationships for type integration (plus other datatypes!) • Customizable save process via dynamic triggers • Custom tooling and automated setup via Apex DDL • Custom datatypes for fields • Even more stuff in the longer term! Summary
  • 52. Available now Spring ’16 Summer ’16 Winter ’17 Beyond Metadata Relationships Apex DDL Dynamic Triggers Custom Datatypes Extra-super-special safe harbor! Roadmap Pilot GA Pilot GA GA Pilot GA
  • 53. Share Your Feedback, and Win a GoPro! 3 Earn a GoPro prize entry for each completed survey Tap the bell to take a survey2Enroll in a session1