tag:blogger.com,1999:blog-72498272734683080812024-02-21T02:50:41.710+13:00Daniel Ballinger's FishOfPrey.compublic class FishOfPrey : IDevelop
{
}FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comBlogger458125tag:blogger.com,1999:blog-7249827273468308081.post-53171337844589289852021-03-22T14:52:00.000+13:002021-03-22T14:52:44.163+13:00FuseIT SFDC Explorer 3.16.21081.2 - Spring '21<p>Another roundup of some of the changes to the <a href="http://www.fuseit.com/explorer">FuseIT SFDC Explorer</a> since the <a href="http://www.fishofprey.com/2020/07/fuseit-sfdc-explorer-315202093-summer-20.html">3.15.20209.3</a> release.</p>
<h2>Apex class and trigger version highlighting</h2>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnzFBOEfSfbtXIUYD7XQQ231OI9Ho3GuzIH-bNxzYJdVloO9mU4KjK9rPE6Z-724ZrbsdWdKuJYpttvtV8Ol3LZ6Aiky160Mgd9WWFyEeq6lBYI5z5zrtIT651LFtkNxV9CBS6DhYmGM3d/s811/ApiVersionListing.png" style="display: block; padding: 1em 0; text-align: center; clear: right; float: right;"><img alt="" border="0" width="320" data-original-height="289" data-original-width="811" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnzFBOEfSfbtXIUYD7XQQ231OI9Ho3GuzIH-bNxzYJdVloO9mU4KjK9rPE6Z-724ZrbsdWdKuJYpttvtV8Ol3LZ6Aiky160Mgd9WWFyEeq6lBYI5z5zrtIT651LFtkNxV9CBS6DhYmGM3d/s320/ApiVersionListing.png"/></a></div>
<p>Ideally all apex classes and triggers within an org would be kept within the <a href="https://salesforce.stackexchange.com/q/188880/102">last 3 years</a> releases (the last 9 API versions). The API version column will be coloured to indicate how far behind a particular class or trigger is.</p>
<h2 style="clear: both;">Export metadata packages from package builder</h2>
<div class="separator" style="clear: all;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCO1kS0pC7Tg-FVsgTCvIlBHoWeJuhLrK1nD3mnm4uJi2IcCDi_D_ywzyORj7_28ih6qqvOv-Hgkc1ScjMbp8qjHfOrlsHovqVhSCTa2SiVpN9EM7MgfMIsHwkj1_E6g8eBOluJtFU8VOa/s458/PackageExportButtons.png" style="display: block; padding: 1em 0; text-align: center; clear: right; float: right;"><img alt="" border="0" width="320" data-original-height="193" data-original-width="458" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCO1kS0pC7Tg-FVsgTCvIlBHoWeJuhLrK1nD3mnm4uJi2IcCDi_D_ywzyORj7_28ih6qqvOv-Hgkc1ScjMbp8qjHfOrlsHovqVhSCTa2SiVpN9EM7MgfMIsHwkj1_E6g8eBOluJtFU8VOa/s320/PackageExportButtons.png"/></a></div>
<p>Added buttons to "Deploy Selected Files" package builder to export the selected metadata as a package. Either a complete zip or just the package.xml</p>
<h2 style="clear:both;">Other changes 3.16</h2>
<ul>
<li>SFDCExplorer: Surface exceptions when listing Salesforce reports via a dialog.</li>
<li>The sObject metadata DataCache no longer internally stores unique mappings for field describes, relationships, or childrelationships. These are still accessible via existing methods.</li>
<li>Complete update to Spring `21 (v51.0). Update the Bulk API XSD.</li>
<li>SFDCExplorer: Detect if there are metadata API version changes when building up a package to deploy</li>
<li>SFDCExplorer: double click to login as an SFDX CLI org.</li>
<li>SFDCExplorer: Context menu option to format a SOQL query in a debug log row.</li>
<li>SFDCExplorer: Improve Executed Units support for workflow and flow events.</li>
<li>Improve support for deploying Profile metadata</li>
<li>Salesforce MetadataServiceWrapper - Expose CreatePackageXmlAsString to create the package.xml for a collection of metadata paths and return it as a string.</li>
<li>SFDCExplorer: Expose the debug log request identifier in the logs view.</li>
<li>SFDCExplorer: Highlight Flow errors in the Apex log timeline</li>
<li>SFDCExplorer: Authenticate from serverId and URL in query string</li>
<li>Split out OAuth (RefreshToken) and JWT LoginDetails to dedicated objects. Added new SfdxLoginDetails for connection strings against the SFDX CLI.</li>
<li>Improve formatting of SalesforceResultException FailedSaveResults.</li>
<li>Support for metadata deployment of static resources</li>
<li>SalesforceIdKeyPrefix - Raise warnings if there is a keyprefix conflict for the current Salesforce user.</li>
<li>WSDL2Apex: Expand ability to search for missing XML Namespaces</li>
<li>Support for deploying Profile Metadata</li>
<li>SFDC Explorer: Improve error handling when there is a timeout retrieving the sObject metadata to populate the entity tree. Retry with a reduced batch size from the detault 100 sObjects.</li>
<li>Weekly Data Export tooling - handle premature response stream termination. Improve logging status messages related to downloading data exports.</li>
<li>SFDCExplorer: Deploy Profile Metadata</li>
<li>SFDCExplorer: handle exceptions with checking test status via polling</li>
</ul>FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-82659376409125421992021-02-11T11:07:00.008+13:002021-03-25T09:52:32.117+13:00Salesforce Glossary - An unofficial list of Salesforce terms and acronyms <p>This list is by no means exhaustive. It's more a random collection to terms and acryoums that get thrown around with Salesforce work that might not always be readily apparent. There is an official <a href="https://help.salesforce.com/articleView?id=glossary.htm&type=5">Glossary</a> provided by Salesforce.</p>
<p>Where terms may have alternative meanings I've focused on the Salesforce usage.</p>
<p>I've been slowly compiling this over time with the intention of publishing it when it reaches some addiquate level of completness. However, it has become apparent that this will be more of a living blog post that I'll update over time. Please let me know if there are gaps or mistakes that need to be corrected.</p>
<p id="glossary_rolodex"><a name="glossary_rolodex"></a>
<a href="#A">
<strong>A</strong>
</a> |<a href="#B">
<strong>B</strong>
</a> |<a href="#C">
<strong>C</strong>
</a> |<a href="#D">
<strong>D</strong>
</a> |<a href="#E">
<strong>E</strong>
</a> |<a href="#F">
<strong>F</strong>
</a> |<a href="#G">
<strong>G</strong>
</a> |<a href="#H">
<strong>H</strong>
</a> |<a href="#I">
<strong>I</strong>
</a> |<a href="#J">
<strong>J</strong>
</a> |<a href="#K">
<strong>K</strong>
</a> |<a href="#L">
<strong>L</strong>
</a> |<a href="#M">
<strong>M</strong>
</a> |<a href="#N">
<strong>N</strong>
</a> |<a href="#O">
<strong>O</strong>
</a> |<a href="#P">
<strong>P</strong>
</a> |<a href="#Q">
<strong>Q</strong>
</a> |<a href="#R">
<strong>R</strong>
</a> |<a href="#S">
<strong>S</strong>
</a> |<a href="#T">
<strong>T</strong>
</a> |<a href="#U">
<strong>U</strong>
</a> |<a href="#V">
<strong>V</strong>
</a> |<a href="#W">
<strong>W</strong>
</a> |<a href="#X">
<strong>X</strong>
</a> |<a href="#Y">
<strong>Y</strong>
</a> |<a href="#Z">
<strong>Z</strong>
</a>
</p>
<div>
<h2 name="A" id="A">A</h2>
<dl>
<dt>AE</dt>
<dd>"Account Executive" - Sales point of contact at Salesforce that handles the client relationship. Sells product licenses.</dd>
<dt>ACV</dt>
<dd><a href="https://www.salesforce.com/resources/articles/what-is-acv-in-sales/">Annualized Contractual Value</a></dd>
<dt>Apex</dt>
<dd><blockquote>Apex is a strongly typed, object-oriented programming language that allows developers to execute flow and transaction control statements on Salesforce servers in conjunction with calls to the API. Using syntax that looks like Java and acts like database stored procedures, Apex enables developers to add business logic to most system events, including button clicks, related record updates, and Visualforce pages. Apex code can be initiated by Web service requests and from triggers on objects.</blockquote> <a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_intro_what_is_apex.htm">Source</a></dd>
<dt>Aura</dt>
<dd>Aura Components were the predecessor to <a href="#LWC">Lightning Web Components</a> before more of the implementation stack was supported by web standard. See <a href="https://developer.salesforce.com/blogs/2018/12/introducing-lightning-web-components.html">Introducing Lightning Web Components</a></dd>
<dt>AmpScript</dt>
<dd>The proprietary scripting language for Marketing Cloud</dd>
<dt>Aloha Apps</dt>
<dd>Older terminology for App Exchange apps that didn't count towards your orgs limits. <a href="https://trailblazer.salesforce.com/ideaView?id=08730000000HEXq">Source</a></dd>
<dt>APAC</dt>
<dd>Asia Pacific & Australia regions</dd>
<dt>AMER</dt>
<dd>US, Canada & Latin America regions</dd>
</dl>
</div>
<div>
<h2 name="B" id="B">B</h2>
<dl>
<dt>Bulkified / Bulkification</dt>
<dd>Code and processes that are designed to work on multiple records at once rather than one at a time (I.e. in bulk). This is particularly relavant to SOQL queries and DML operations where doing operations on records individually may lead to limits being hit.</dd>
<dt>Black Tab</dt>
<dd>An internal tab available to Salesforce employees and support that can toggle specific features and sdjust limits in customer orgs. See <a href="https://salesforce.stackexchange.com/q/366/102">What is the Black Tab?</a></dd>
</dl>
</div>
<div>
<h2 name="C" id="C">C</h2>
<dl>
<dt>CMDT</dt>
<dd><a href="https://help.salesforce.com/articleView?id=custommetadatatypes_overview.htm&type=5">Custom Metadata Type</a></dd>
<dt>CPQ</dt>
<dd>(Configure, Price, Quote) - formerly Steelbrick. This has now been rebranded Revenue Cloud.</dd>
<dt>CFP<dt>
<dd>Call for Presenters</dd>
<dt>COA<dt>
<dd>Partner <a href="https://partners.salesforce.com/s/education/appinnovators/Channel_Order_App">Channel Order App</a> - "enables you to create, submit, and track orders with Salesforce"</dd>
<dt>CLI</dt>
<dd><a href="https://developer.salesforce.com/tools/sfdxcli">[SFDX] Command Line Interface</a></dd>
<dt>Comfortable Shoes</dt>
<dd>The battle cry of attending an inperson <a href="#dreamforce">Dreamforce</a> event where you will be doing <b>a lot</b> of walking.</dd>
<dt>Code Coverage<dt>
<dd>"Code coverage indicates how many executable lines of code in your classes and triggers have been exercised by test methods." - <a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_code_coverage_intro.htm">source</a></dd>
<dt>CIM</dt>
<dd><a href="https://cloudinformationmodel.org/">Cloud Information Model</a></dd>
<dt>Community Clould</dt>
<dd>Rebranded Experience Cloud</dd>
</dl>
</div>
<div>
<h2 name="D" id="D">D</h2>
<dl>
<dt>Daryl Shaber<dt>
<dd>"We Are Daryl Shaber" - <a href="https://www.salesforce.com/content/blogs/us/en/2011/08/the-community-conference-kicks-of-dreamforce-11.html">Reference</a> </dd>
<dt>Deployment Fish</dt>
<dd>The result of a bug in the changeset deployment monitoring UI that would stretch the circular control into veriaous shapes. Often fish like in nature.</dd>
<dt>DML</dt>
<dd><a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_dml.htm">Data Manipulation Language</a>. The <b>C</b>reate, <b>U</b>pdate, and <b>D</b>elete parts of the database CRUD operations. Retrieve is handled via SOQL queries.</dd>
<dt>Dwarf</dt>
<dd>The occasional Oracle error code that leaks out of Salesforce will include references to one of the seven dwarfs. See <a href="https://salesforce.stackexchange.com/q/76423/102">Salesforce, Oracle and the Seven Dwarfs</a>.</dd>
<dt>D&B</dt>
<dd>"Dun & Bradstreet" - <a href="https://help.salesforce.com/articleView?id=dnb_company_fields.htm&type=5">D&B Company Fields</a></dd>
<dt>Dreamforce</dt>
<dd>Annual Salesforce user conference.</dd>
<dt>DRAES</dt>
<dd>Designing Record Access for Enterprise Scale. <a href="https://developer.salesforce.com/docs/atlas.en-us.draes.meta/draes/draes_preface.htm">Reference</a></dd>
</dl>
</div>
<div>
<h2 name="E" id="E">E</h2>
<dl>
<dt>ESAPI</dt>
<dd><a href="https://github.com/forcedotcom/force-dot-com-esapi">Enterprise Security API</a></dd>
<dt>Evergreen</dt>
<dd>Internal project code name for Salesforce Functions</dd>
<dt>Environment Hub</dt>
<dd>"allows partners to view, connect, create, and log in to multiple Salesforce organizations from one location" - <a href="https://partners.salesforce.com/s/education/general/Environment_Hub">Reference</a></dd>
<dt>EMEA</dt>
<dd>Europe, Middle East & Africa regions</dd>
</dl>
</div>
<div>
<h2 name="F" id="F">F</h2>
<dl>
<dt>[Salesforce] Functions</dt>
<dd>Previously known as Evergreen. The ability to write code that integrates with Salesforce data and events in a serverless environment.</dd>
</dl>
<dl>
<dt>Falcon</dt>
<dd>Salesforce CLI plugin built for AppExchange Partners <a href="https://sfdx-isv.github.io/sfdx-falcon/index.html">Reference</a></dd>
</dl>
<dl>
<dt>Field Service Lightning</dt>
<dd>Rebranded Field Service</dd>
</dl>
</div>
<div>
<h2 name="G" id="G">G</h2>
<dl>
<dt>GACK</dt>
<dd>An internal Salesforce error. <a href="https://developer.salesforce.com/blogs/engineering/2015/02/gack.html">What Is A Gack?</a></dd>
</dl>
<dl>
<dt>GA</dt>
<dd>Generally Available - The point where a new Salesforce feature has passed the preview and beta phases and is ready for use.</dd>
</dl>
<dl>
<dt>GUS</dt>
<dd>Grand Unified System - Internal Salesforce tool that handles tickets, user stories, bugs, builds and releases. <a href="https://developer.salesforce.com/blogs/engineering/2014/08/meet-gus-keeping-salesforce-agile.html">Meet GUS: The Grand Unified System That Keeps Salesforce Agile</a></dd>
</dl>
<dl>
<dt>GS0</dt>
<dd>Pre-release org instance for testing before a release reaches sandboxes.</dd>
</dl>
</div>
<div>
<h2 name="H" id="H">H</h2>
<dl>
<dt>Happy Soup</dt>
<dd>A phrase coined by Wade Wegner at TrailheadDX 2017 to describe how metadata was deployed to a production org without any strongly defined boundaries between applications/components.</dd>
<dt>Hyperforce</dt>
<dd>The capability to deploy Salesforce on major public cloud platforms like Azure, AWS, Google, and Alibaba. This helps address data residency and complicance requirements. <a href="https://www.salesforce.com/products/platform/hyperforce/">Reference</a><br/><a href="https://help.salesforce.com/articleView?id=000356459&type=1&mode=1">Introducing Hyperforce - General Information & FAQ</a>/dd>
</dl>
</div>
<div>
<h2 name="I" id="I">I</h2>
<dl>
<dt>IaaS</dt>
<dd>Infrastructure as a Service</dd>
<dt>ID</dt>
<dd>A Salesforce record identifier. Either 15 or 18 characters long - <a href="https://salesforce.stackexchange.com/q/1653/102">What are Salesforce ID's composed of?</a></dd>
</dl>
<dl>
<dt>ISV</dt>
<dd>Independent software vendor</dd>
</dl>
</div>
<div>
<h2 name="J" id="J">J</h2>
<dl>
<dt>Jorje</dt>
<dd>Internal codename for the <a href="https://developer.salesforce.com/tools/vscode/en/apex/language-server/">Apex Language Server</a></dd>
</dl>
</div>
<div>
<h2 name="K" id="K">K</h2>
<dl>
<dt>Keyprefix</dt>
<dd>The first 3 characters of a Salesforce ID. These can be used to <a href="http://www.fishofprey.com/2011/09/obscure-salesforce-object-key-prefixes.html">determine the sObject type</a>.</dd>
</dl>
</div>
<div>
<h2 name="L" id="L">L</h2>
<dl>
<dt>LMA</dt>
<dd>License Management App - Used by ISV Partners to manage applications</dd>
<dt>LWC</dt>
<dd>Lightning Web Component</dd>
<dt>LWR</dt>
<dd>Lightning Web Runtime</dd>
<dt>Limits</dt>
<dd><blockquote>"Because Apex runs in a multitenant environment, the Apex runtime engine strictly enforces limits so that runaway Apex code or processes don’t monopolize shared resources."</blockquote> <a href="https://developer.salesforce.com/docs/atlas.en-us.salesforce_app_limits_cheatsheet.meta/salesforce_app_limits_cheatsheet/salesforce_app_limits_platform_apexgov.htm">Source</a></dd>
</dl>
</div>
<div>
<h2 name="M" id="M">M</h2>
<dl>
<dt>Metadata</dt>
<dd><blockquote>"Metadata are the assets in your org (assets being objects, tabs, classes, etc). These metadata assets are also called metadata components."</blockquote> <a href="https://trailhead.salesforce.com/en/content/learn/modules/package-xml/package-xml-adventure#-----------what-is-metadata--">Source</a> </dd>
<dt>Marketing Cloud</dt>
<dd><blockquote>"Salesforce Marketing Cloud is a provider of digital marketing automation and analytics software and services."</blockquote> <a href="https://en.wikipedia.org/wiki/Salesforce_Marketing_Cloud">Source</a></dd>
<dt>MSA</dt>
<dd>Master Subscription Agreement - <a href="https://www.salesforce.com/content/dam/web/en_us/www/documents/legal/salesforce_MSA.pdf">Reference</a></dd>
</dl>
</div>
<div>
<h2 name="N" id="N">N</h2>
<dl>
<dt></dt>
<dd></dd>
</dl>
</div>
<div>
<h2 name="O" id="O">O</h2>
<dl>
<dt>OWD</dt>
<dd>Organization-Wide Defaults</dd>
<dt>OCLIF</dt>
<dd>Open CLI Framework</dd>
<dt>OLI</dt>
<dd>OpportunityLineItem / Opportunity Product</dd>
<dt>Org62</dt>
<dd>The Salesforce Org that they use internally to run Salesforce. </dd>
</dl>
</div>
<div>
<h2 name="P" id="P">P</h2>
<dl>
<dt>PaaS</dt>
<dd>Platform as a Service</dd>
<dt>Pod</dt>
<dd>A collection of Salesforce servers that is required to run the complete application. A.K.A Instance</dd>
<dt>PAM</dt>
<dd><a href="https://partners.salesforce.com/s/education/general/Partner_Account_Manager">Partner Account Manager</a></dd>
<dt>Polymorphic Lookup</dt>
<dd>A releationship field that can point to more than one entity.</dd>
<dt>PBO</dt>
<dd>Partner Business Org - a production Salesforce enviroment for Salesforce Partners - <a href="https://partners.salesforce.com/s/education/general/Partner_Business_Org">Docs<a/></dd>
<dt>PDO</dt>
<dd><a href="https://partners.salesforce.com/s/education/general/Product_Development_Outsourcer">Product Development Outsourcers</a></dd>
</dl>
</div>
<div>
<h2 name="Q" id="Q">Q</h2>
<dl>
<dt>Quiddity</dt>
<dd><blockquote>PHILOSOPHY "the inherent nature or essence of someone or something."</blockquote> Exposed in Apex to represent the type of a transaction. <a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_enum_System_Quiddity.htm">Docs</a></dd>
</dl>
</div>
<div>
<h2 name="R" id="R">R</h2>
<dl>
<dt></dt>
<dd></dd>
</dl>
</div>
<div>
<h2 name="S" id="S">S</h2>
<dl>
<dt>SaaS</dt>
<dd>Software as a Service</dd>
<dt>Safe Harbor</dt>
<dd>The precursor to the <a href="https://investor.salesforce.com/safe-harbor/default.aspx">forward-looking statement</a></dd>
<dt>S2S</dt>
<dd>Salesforce to Salesforce</dd>
<dt>SFDC</dt>
<dd>Salesforce Dot Com</dd>
<dt>SFDX</dt>
<dd>Salesforce DX (Developer Experience)</dd>
<dt>SOQL</dt>
<dd>Salesforce Object Query Language. A varient of SQL specifically for Salesforce that is used to query Salesforce data. <a href="https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql.htm">Reference</a></dd>
<dt>SLDS</dt>
<dd>Salesforce Lightning Design System <a href="https://lightningdesignsystem.com/">https://lightningdesignsystem.com/</a>
<blockquote>Brand and product design guidelines, Design Patterns and Component Blueprints for creating unified UI in the Salesforce ecosystem.</blockquote>
</dd>
<dt>SFDO</dt>
<dd><a href="https://www.salesforce.org/">Salesforce.org</a></dd>
<dt>sControl</dt>
<dd>Deprecated customization control for Salesforce that was superseded by Visualforce pages. <a href="https://help.salesforce.com/articleView?id=dev_about_scontrols.htm&type=5">Docs</a></dd>
<dt>SObject</dt>
<dd>An abstract base class for Salesforce record types that are stored in the database. <a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_methods_system_sobject.htm">Docs</a> </dd>
<dt>Stealbrick / CPQ</dt>
<dd>Stealbrick Quote Quickly (SBQQ)<dd>
<dt>Source of truth</dt>
<dd>The data source that contains the authoriative data about a whole object.</dd>
<dt>SI</dt>
<dd>Systems Integrators</dd>
<dt>Security Token</dt>
<dd>A case-sensitive alhanumberic key that is appended to the users password when authenticating against the Salesforce API. <a href="https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_concepts_security.htm#topic-title_login_token">Docs</a></dd>
<dt>Site Switching</dt>
<dd><blockquote>Each Salesforce instance is built and maintained in two geographically separate locations. An instance is actively served from one location (the active site) with transactions replicating in near real-time to the other completely redundant location (the ready site). A site switch means the locations of an instance’s active and ready sites are swapped, making the ready site the new active site and vice versa -- the instance name does not change.</blockquote> <a href="https://help.salesforce.com/articleView?id=000337828&type=1&mode=1">Reference</a></dd>
</dl>
</div>
<div>
<h2 name="T" id="T">T</h2>
<dl>
<dt>Tableau CRM</dt>
<dd>Formerly Einstein Analytics</dd>
<dt>TDTM</dt>
<dd>Table-Driven Trigger Management - "a tool to managed apex triggers". <a href="https://trailhead.salesforce.com/en/content/learn/modules/eda-configuration-and-data-import/automate-tasks-with-table-driven-trigger-management-tdtm">Source</a></dd>
</dl>
</div>
<div>
<h2 name="U" id="U">U</h2>
<dl>
<dt>Upsert</dt>
<dd>A database operation that will adjust between an insert and update depending on the record in question. <a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_dml_examples_upsert.htm?search_text=upsert">Reference</a></dd>
<dt>Universal Containers</dt>
<dd>A fictional shipping container company referenced by Salesforce, especially in various certification exam questions and Trailhead modules.</dd>
</dl>
</div>
<div>
<h2 name="V" id="V">V</h2>
<dl>
<dt>Visualforce</dt>
<dd><blockquote>Visualforce is a framework that allows developers to build sophisticated, custom user interfaces that can be hosted natively on the Lightning platform. The Visualforce framework includes a tag-based markup language, similar to HTML, and a set of server-side “standard controllers” that make basic database operations, such as queries and saves, very simple to perform.</blockquote> <a href="https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_intro_what_is_it.htm">Source</a></dd>
</dl>
<dl>
<dt>Vlocity</dt>
<dd>Rebranded Salesforce Industries</dd>
</dl>
</div>
<div>
<h2 name="W" id="W">W</h2>
<dl>
<dt>WSDL2Apex</dt>
<dd>A Salesforce tool for generating stub Apex classes from a SOAP WSDL. <a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_callouts_wsdl2apex_gen_code.htm">Reference</a></dd>
</dl>
</div>
<div>
<h2 name="X" id="X">X</h2>
<dl>
<dt></dt>
<dd></dd>
</dl>
</div>
<div>
<h2 name="Y" id="Y">Y</h2>
<dl>
<dt></dt>
<dd></dd>
</dl>
</div>
<div>
<h2 name="Z" id="Z">Z</h2>
<dl>
<dt></dt>
<dd></dd>
</dl>
</div>
<div>
<h2 name="Numbers" id="Numbers">#</h2>
<dl>
<dt>1GP</dt>
<dd>First-Generation Managed Packaging - a Zip file of metadata components that can be deployed to an org via the Metadata API. They typically form an application or piece of functionality. For distribution via the app exchange they are created via a packaging org. <a href="https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_build_release.htm">Docs</a></dd>
</dl>
<dl>
<dt>2GP</dt>
<dd>Second-Generation Managed Packaging - Salesforce CLI (rather than Org) based packaging. <a href="https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_dev2gp.htm">Docs</a> and <a href="https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_dev2gp_comparison.htm">Comparison of 2GP and 1GP Managed Packages</a></dd>
</dl>
</div>
<dl>
</dl>FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-85866653957740626962020-12-08T08:20:00.002+13:002020-12-08T08:42:40.566+13:00Dreamforce/DreamTX 2020 Session Picks<p>Here are some of my current picks for Dreamforce/DreamTX 2020 sessions. Many of these sessions have repeats to better accomidate other timezones if required.</p>
<h1>Monday, December 14th PST | Tuesday, December 15th NZDT</h1>
<h2><a href="https://trailblazer.salesforce.com/myagenda?eventId=a1Q4V00002DWxkY#/session/a2q4V0000032Oi6QAE">Salesforce Platform: Innovation Roadmap</a></h2>
<blockquote>Join us to learn about the latest Salesforce Platform innovations and product roadmap. Whether you're building with low-code tools, developing scalable apps on Heroku, or working to deliver a better employee experience, this episode will highlight new and upcoming Salesforce Platform products and features that make your job easier.</blockquote>
<h1>Thusrday, December 17th PST | Friday, December 18th NZDT</h1>
<h2><a href="https://trailblazer.salesforce.com/sessions?eventId=a1Q4V00002DWxkY#/session/a2q4V000002qglrQAA">DreamTX Welcome Day 4: Skill Up with Trailhead</a></h2>
<blockquote>Join us to learn about the latest innovation on the Salesforce Platform to go digital fast, scale with confidence, and empower everyone.</blockquote>
<h2><a href="https://trailblazer.salesforce.com/myagenda?eventId=a1Q4V00002DWxkY#/session/a2q4V000002BOJ1QAO">Ask the Experts Live Q&A: Developer Experience</a></h2>
<blockquote>Join us to ask about how Salesforce is helping to make you a more productive salesforce developer, with experts from Apex, Salesforce Developer Tools and APIs with your host Heather Storm.</blockquote>
<h2><a href="https://trailblazer.salesforce.com/myagenda?eventId=a1Q4V00002DWxkY#/session/a2q4V000002BOA4QAO">Build Connected Experiences on Salesforce</a></h2>
<blockquote>Join us and learn how to build modern customer and employee experiences on the Salesforce Platform. We’ll explore the latest innovations in Lightning Web Components, event-driven architectures, and Salesforce Functions.</blockquote>
<h2><a href="https://trailblazer.salesforce.com/myagenda?eventId=a1Q4V00002DWxkY#/session/a2q4V000002BOA9QAO">Building Amazing Integrations with Apex</a></h2>
<blockquote>Apex is the workhorse of Salesforce development. Increasingly, however, more and more of our business logic takes the form of asynchronous work. Join us to learn what's new and upcoming in Asynchronous Apex including Salesforce Functions.</blockquote>
<h2><a href="https://trailblazer.salesforce.com/myagenda?eventId=a1Q4V00002DWxkY#/session/a2q4V000002BOAEQA4">What’s New With Lightning Web Components</a></h2>
<blockquote>UI is the foundation of every app, and the Lightning Web Component Framework provides the building blocks needed to create new experiences that work inside and outside of Salesforce. Learn how to create custom interactions using the new NPM Base Components package, customize those interactions with SLDS styling hooks, then extend those interactions with enhanced LockerService support for 3rd party libraries. Finally, we’ll share a sneak peak of an upcoming pilot feature that will make it even easier to add data to your UI.</blockquote>
<h2><a href="https://trailblazer.salesforce.com/myagenda?eventId=a1Q4V00002DWxkY#/session/a2q4V000002BOJGQA4">Ask the Experts Live Q&A: Roadmap Insights For Partners</a></h2>
<blockquote>Where are we going from here? Learn from our AppExchange and Platform experts as they share what Salesforce technologies should be top of mind for partners and how these technologies will help you grow your business. This session is live and our panel looks forward to engaging into a passionate Q&A.</blockquote>
<h2><a href="https://trailblazer.salesforce.com/myagenda?eventId=a1Q4V00002DWxkY#/session/a2q4V000002BOAOQA4">See the Future of APIs at Salesforce</a></h2>
<blockquote>APIs are the glue that holds together most complex business processes. But despite their importance, the developer experience behind API use is often ignored. Join us for a sneak peek at brand new capabilities for using APIs from across the Salesforce Platform. We'll dive into our latest API innovations, such as the new Composite Graph API, and showcase never before seen features that will change how you learn, discover, and employ APIs in your development process.</blockquote>
<h2><a href="https://trailblazer.salesforce.com/myagenda?eventId=a1Q4V00002DWxkY#/session/a2q4V000002BOATQA4">Everything New in Salesforce Developer Tools</a></h2>
<blockquote>Your productivity starts and ends with the tools you use. Learn how Salesforce Developer Tooling can help you collaborate more effectively with your whole team. We'll show you the latest updates in Dev Tools including the new SOQL Query Builder.</blockquote>
<hr/>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0wTttt1qxLsnaNdHmqkFj4eaPIG3gTS6wgUSeEYY_TkGf81Wkv3GILaiTxNaZi5NWt-anDulgMTo4gsLI62uHiMRhxNf3aFMg_5DqE-VEe1U4ocV9CGQviM2qQz-FPb8dsf5hdLPVWBOJ/s381/Theme.png" style="display: block; padding: 1em 0; text-align: center; clear: right; float: right;"><img alt="" border="0" height="320" data-original-height="381" data-original-width="321" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0wTttt1qxLsnaNdHmqkFj4eaPIG3gTS6wgUSeEYY_TkGf81Wkv3GILaiTxNaZi5NWt-anDulgMTo4gsLI62uHiMRhxNf3aFMg_5DqE-VEe1U4ocV9CGQviM2qQz-FPb8dsf5hdLPVWBOJ/s320/Theme.png"/></a></div>
<p>Note that most of these sessions have repeats in other timezones. You can use the Themes to filter search results by region.</p>FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-56040931917153733242020-10-12T14:29:00.004+13:002020-12-07T10:59:28.167+13:00Mapping between Salesforce Permission Name and the Label<p>I recently ran into <a href="https://salesforce.stackexchange.com/q/322146/102">a minor challenge</a> when deploying a Profile's metadata to an org when it came back with the error message:</p>
<blockquote>
"You may not modify the permission Run Macros on Multiple Records while editing a Standard Profile"
</blockquote>
<p>The profiles metadata doesn't contain the string "Run Macros on Multiple Records", so how do I know which <code>userPermissions</code> element I need to modify? I was able to narrow it down from the source diff on the file to <code>BulkMacrosAllowed</code>.</p>
<p>So my primary problem was solved, but it did leave me wondering why I couldn't find a more complete mapping of permission API names and the corresponding UI labels.</p>
<p>A <a href="https://salesforce.stackexchange.com/q/322146/102">small amount of research</a> revealed the required information was in the PermissionSet field metadata. So then I just needed to iterate that metadata and put it into a more useful format (I.e. something I can Google).</p>
<p>The following was hastily extracted from a Summer '20 Dev org and merged with a Scratch Org from the same vintage using the v49.0 API. Your results may vary.</p>
<p>Updated for Winter '21 (v50.0). Just to be confusing it appears Salesforce has changed a couple of the UI Labels. So I've started keeping a <a href="https://gist.github.com/FishOfPrey/aaf8a0f2c4cc76e82395f6aa479ac187">versioned history</a> of the changes to this page.</p>
<table border="1px">
<tbody>
<tr>
<th>API Name</th><th>UI Label</th>
</tr>
<!-- Source from https://gist.github.com/FishOfPrey/aaf8a0f2c4cc76e82395f6aa479ac187 -->
<tr><td>AccessCMC</td><td>Access Community Management</td></tr>
<tr><td>AccessContentBuilder</td><td>Access drag-and-drop content builder</td></tr>
<tr><td>AccountSwitcherUser</td><td>Account Switcher User</td></tr>
<tr><td>ActivateContract</td><td>Activate Contracts</td></tr>
<tr><td>ActivateOrder</td><td>Activate Orders</td></tr>
<tr><td>ActivitiesAccess</td><td>Access Activities</td></tr>
<tr><td>AddAnalyticsRemoteConnections</td><td>Add Analytics Remote Connections</td></tr>
<tr><td>AddDirectMessageMembers</td><td>Add People to Direct Messages</td></tr>
<tr><td>AddWaveNotificationRecipients</td><td>Notification Emails: Add Recipients</td></tr>
<tr><td>AllowEmailIC</td><td>Email-Based Identity Verification Option</td></tr>
<tr><td>AllowLightningLogin</td><td>Lightning Login User</td></tr>
<tr><td>AllowUniversalSearch</td><td>Knowledge One</td></tr>
<tr><td>AllowViewEditConvertedLeads</td><td>View and Edit Converted Leads</td></tr>
<tr><td>AllowViewKnowledge</td><td>Allow View Knowledge</td></tr>
<tr><td>ApexRestServices</td><td>Apex REST Services</td></tr>
<tr><td>ApiEnabled</td><td>API Enabled</td></tr>
<tr><td>AssignPermissionSets</td><td>Assign Permission Sets</td></tr>
<tr><td>AssignTopics</td><td>Assign Topics</td></tr>
<tr><td>AuthorApex</td><td>Author Apex</td></tr>
<tr><td>B2BMarketingAnalyticsUser</td><td>Create B2B Marketing Analytics Apps</td></tr>
<tr><td>BotManageBots</td><td>Manage Bots</td></tr>
<tr><td>BotManageBotsTrainingData</td><td>Manage Bots Training Data</td></tr>
<tr><td>BulkApiHardDelete</td><td>Bulk API Hard Delete</td></tr>
<tr><td>BulkMacrosAllowed</td><td>Run Macros on Multiple Records</td></tr>
<tr><td>CampaignInfluence2</td><td>Campaign Influence</td></tr>
<tr><td>CanApproveFeedPost</td><td>Can Approve Feed Post and Comment</td></tr>
<tr><td>CanEditDataPrepRecipe</td><td>Edit Dataset Recipes</td></tr>
<tr><td>CanEditPrompts</td><td>Manage Prompts</td></tr>
<tr><td>CanInsertFeedSystemFields</td><td>Insert System Field Values for Chatter Feeds</td></tr>
<tr><td>CanManageMaps</td><td>Manage Analytics Custom Maps</td></tr>
<tr><td>CanUseNewDashboardBuilder</td><td>Drag-and-Drop Dashboard Builder</td></tr>
<tr><td>CanVerifyComment</td><td>Verify Answers to Chatter Questions</td></tr>
<tr><td>ChangeDashboardColors</td><td>Change Dashboard Colors</td></tr>
<tr><td>ChatterComposeUiCodesnippet</td><td>Allow Inclusion of Code Snippets from UI</td></tr>
<tr><td>ChatterEditOwnPost</td><td>Edit My Own Posts</td></tr>
<tr><td>ChatterEditOwnRecordPost</td><td>Edit Posts on Records I Own</td></tr>
<tr><td>ChatterFileLink</td><td>Create Public Links</td></tr>
<tr><td>ChatterInternalUser</td><td>Chatter Internal User</td></tr>
<tr><td>ChatterInviteExternalUsers</td><td>Invite Customers To Chatter</td></tr>
<tr><td>ChatterOwnGroups</td><td>Create and Own New Chatter Groups</td></tr>
<tr><td>CloseConversations</td><td>Close Conversation Threads</td></tr>
<tr><td>ConfigCustomRecs</td><td>Configure Custom Recommendations</td></tr>
<tr><td>ConnectOrgToEnvironmentHub</td><td>Connect Organization to Environment Hub</td></tr>
<tr><td>ConsentApiUpdate</td><td>Update Consent Preferences Using REST API</td></tr>
<tr><td>ContentAdministrator</td><td>Manage Salesforce CRM Content</td></tr>
<tr><td>ContentHubOnPremiseUser</td><td>Files Connect On-premises</td></tr>
<tr><td>ContentHubUser</td><td>Files Connect Cloud</td></tr>
<tr><td>ContentWorkspaces</td><td>Access Libraries</td></tr>
<tr><td>ConvertLeads</td><td>Convert Leads</td></tr>
<tr><td>CreateCustomizeDashboards</td><td>Create and Customize Dashboards</td></tr>
<tr><td>CreateCustomizeFilters</td><td>Create and Customize List Views</td></tr>
<tr><td>CreateCustomizeReports</td><td>Create and Customize Reports</td></tr>
<tr><td>CreateDashboardFolders</td><td>Create Dashboard Folders</td></tr>
<tr><td>CreateLtngTempFolder</td><td>Create Folders for Lightning Email Templates</td></tr>
<tr><td>CreateLtngTempInPub</td><td>Manage Public Lightning Email Templates</td></tr>
<tr><td>CreatePackaging</td><td>Create AppExchange Packages</td></tr>
<tr><td>CreateReportFolders</td><td>Create Report Folders</td></tr>
<tr><td>CreateReportInLightning</td><td>Report Builder (Lightning Experience)</td></tr>
<tr><td>CreateTopics</td><td>Create Topics</td></tr>
<tr><td>CreateWorkBadgeDefinition</td><td>Create custom Badge Definitions</td></tr>
<tr><td>CreateWorkspaces</td><td>Create Libraries</td></tr>
<tr><td>CustomizeApplication</td><td>Customize Application</td></tr>
<tr><td>CustomMobileAppsAccess</td><td>Access Custom Mobile Apps</td></tr>
<tr><td>CustomSidebarOnAllPages</td><td>Show Custom Sidebar On All Pages</td></tr>
<tr><td>CustomTabBarOnMobile</td><td>New Salesforce Mobile App - Customizable Navigation (Winter '20 Pilot Only)</td></tr>
<tr><td>DataExport</td><td>Weekly Data Export</td></tr>
<tr><td>DelegatedTwoFactor</td><td>Manage Multi-Factor Authentication in User Interface</td></tr>
<tr><td>DeleteActivatedContract</td><td>Delete Activated Contracts</td></tr>
<tr><td>DeleteTopics</td><td>Delete Topics</td></tr>
<tr><td>DistributeFromPersWksp</td><td>Create Content Deliveries</td></tr>
<tr><td>EditActivatedOrders</td><td>Edit Activated Orders</td></tr>
<tr><td>EditBrandTemplates</td><td>Manage Letterheads</td></tr>
<tr><td>EditCaseComments</td><td>Edit Case Comments</td></tr>
<tr><td>EditEvent</td><td>Edit Events</td></tr>
<tr><td>EditHtmlTemplates</td><td>Edit HTML Templates</td></tr>
<tr><td>EditKnowledge</td><td>Manage Articles</td></tr>
<tr><td>EditMyDashboards</td><td>Edit My Dashboards</td></tr>
<tr><td>EditMyReports</td><td>Edit My Reports</td></tr>
<tr><td>EditOppLineItemUnitPrice</td><td>Edit Opportunity Product Sales Price</td></tr>
<tr><td>EditPublicDocuments</td><td>Manage Public Documents</td></tr>
<tr><td>EditPublicFilters</td><td>Manage Public List Views</td></tr>
<tr><td>EditPublicReports</td><td>Manage Public Reports</td></tr>
<tr><td>EditPublicTemplates</td><td>Manage Public Classic Email Templates</td></tr>
<tr><td>EditReadonlyFields</td><td>Edit Read Only Fields</td></tr>
<tr><td>EditReports</td><td>Create and Customize Reports</td></tr>
<tr><td>EditTask</td><td>Edit Tasks</td></tr>
<tr><td>EditTopics</td><td>Edit Topics</td></tr>
<tr><td>EmailAdministration</td><td>Email Administration</td></tr>
<tr><td>EmailMass</td><td>Mass Email</td></tr>
<tr><td>EmailSingle</td><td>Send Email</td></tr>
<tr><td>EmailTemplateManagement</td><td>Manage Email Templates</td></tr>
<tr><td>EnableCommunityAppLauncher</td><td>Show App Launcher in Communities</td></tr>
<tr><td>EnableNotifications</td><td>Send Outbound Messages</td></tr>
<tr><td>ExportReport</td><td>Export Reports</td></tr>
<tr><td>FeedPinning</td><td>Pin Posts in Feeds</td></tr>
<tr><td>FieldServiceAccess</td><td>Field Service Standard</td></tr>
<tr><td>FieldServiceDispatcher</td><td>Field Service Dispatcher</td></tr>
<tr><td>FieldServiceLastMile</td><td>Field Service Last Mile</td></tr>
<tr><td>FieldServiceMobileApp</td><td>Field Service Mobile</td></tr>
<tr><td>FieldServiceScheduling</td><td>Field Service Scheduling</td></tr>
<tr><td>FlowUFLRequired</td><td>Require Flow User Feature License</td></tr>
<tr><td>ForceTwoFactor</td><td>Multi-Factor Authentication for User Interface Logins</td></tr>
<tr><td>FSCComprehensiveUserAccess</td><td>User license to access Lightning components and features delivered in Financial Services Cloud.</td></tr>
<tr><td>GiveRecognitionBadge</td><td>Give Recognition Badges in Lightning Communities</td></tr>
<tr><td>GovernNetworks</td><td>Manage Communities</td></tr>
<tr><td>HasUnlimitedNBAExecutions</td><td>User Has Unlimited Next Best Action Strategy Executions</td></tr>
<tr><td>HeadlessCMSAccess</td><td>Enable Salesforce CMS Integration</td></tr>
<tr><td>HideReadByList</td><td>Hide the Seen By List</td></tr>
<tr><td>IdentityConnect</td><td>Use Identity Connect</td></tr>
<tr><td>IdentityEnabled</td><td>Use Identity Features</td></tr>
<tr><td>ImportCustomObjects</td><td>Import Custom Objects</td></tr>
<tr><td>ImportLeads</td><td>Import Leads</td></tr>
<tr><td>ImportPersonal</td><td>Import Personal Contacts</td></tr>
<tr><td>InsightsAppAdmin</td><td>Manage Analytics</td></tr>
<tr><td>InsightsAppDashboardEditor</td><td>Create and Edit Analytics Dashboards</td></tr>
<tr><td>InsightsAppEltEditor</td><td>Edit Analytics Dataflows</td></tr>
<tr><td>InsightsAppUploadUser</td><td>Upload External Data to Analytics</td></tr>
<tr><td>InsightsAppUser</td><td>Use Analytics</td></tr>
<tr><td>InsightsCreateApplication</td><td>Create Analytics Apps</td></tr>
<tr><td>InstallPackaging</td><td>Download AppExchange Packages</td></tr>
<tr><td>IotUser</td><td>IoT User</td></tr>
<tr><td>IsotopeAccess</td><td>Salesforce Anywhere on Mobile</td></tr>
<tr><td>IsotopeCToCUser</td><td>Salesforce Anywhere Integration Access</td></tr>
<tr><td>IsotopeLEX</td><td>Salesforce Anywhere in Lightning Experience</td></tr>
<tr><td>LightningConsoleAllowedForUser</td><td>Lightning Console User</td></tr>
<tr><td>LightningExperienceUser</td><td>Lightning Experience User</td></tr>
<tr><td>ListEmailSend</td><td>Allow sending of List Emails</td></tr>
<tr><td>LMEndMessagingSessionUserPerm</td><td>End Messaging Session</td></tr>
<tr><td>LMOutboundMessagingUserPerm</td><td>Agent Initiated Outbound Messaging</td></tr>
<tr><td>LtngPromoReserved01UserPerm</td><td>Remain in Salesforce Classic</td></tr>
<tr><td>ManageAnalyticSnapshots</td><td>Manage Reporting Snapshots</td></tr>
<tr><td>ManageAuthProviders</td><td>Manage Auth. Providers</td></tr>
<tr><td>ManageBusinessHourHolidays</td><td>Manage Business Hours Holidays</td></tr>
<tr><td>ManageC360AConnections</td><td>Connect Org to Customer 360 Audiences</td></tr>
<tr><td>ManageCallCenters</td><td>Manage Call Centers</td></tr>
<tr><td>ManageCases</td><td>Manage Cases</td></tr>
<tr><td>ManageCategories</td><td>Manage Categories</td></tr>
<tr><td>ManageCertificates</td><td>Manage Certificates</td></tr>
<tr><td>ManageChatterMessages</td><td>Manage Chatter Messages and Direct Messages</td></tr>
<tr><td>ManageClearbitIntegration</td><td>Manage your Clearbit Integration</td></tr>
<tr><td>ManageCMS</td><td>Create CMS Workspaces and Channels</td></tr>
<tr><td>ManageContent</td><td>Manage Content Permissions</td></tr>
<tr><td>ManageContentProperties</td><td>Manage Content Properties</td></tr>
<tr><td>ManageContentTypes</td><td>Manage record types and layouts for Files</td></tr>
<tr><td>ManageCssUsers</td><td>Manage Customer Users</td></tr>
<tr><td>ManageCustom</td><td>Manage Custom Permissions</td></tr>
<tr><td>ManageCustomReportTypes</td><td>Manage Custom Report Types</td></tr>
<tr><td>ManageDashbdsInPubFolders</td><td>Manage Dashboards in Public Folders</td></tr>
<tr><td>ManageDashboards</td><td>Manage Dashboards</td></tr>
<tr><td>ManageDataCategories</td><td>Manage Data Categories</td></tr>
<tr><td>ManageDataIntegrations</td><td>Manage Data Integrations</td></tr>
<tr><td>ManageDynamicDashboards</td><td>Manage Dynamic Dashboards</td></tr>
<tr><td>ManageEmailClientConfig</td><td>Manage Email Client Configurations</td></tr>
<tr><td>ManageEncryptionKeys</td><td>Manage Encryption Keys</td></tr>
<tr><td>ManageExchangeConfig</td><td>Manage Lightning Sync</td></tr>
<tr><td>ManageExternalConnections</td><td>Allow user to modify Private Connections</td></tr>
<tr><td>ManageHealthCheck</td><td>Manage Health Check</td></tr>
<tr><td>ManageHubConnections</td><td>Connect Org to Customer 360 Data Manager</td></tr>
<tr><td>ManageInteraction</td><td>Manage Flow</td></tr>
<tr><td>ManageInternalUsers</td><td>Manage Internal Users</td></tr>
<tr><td>ManageIpAddresses</td><td>Manage IP Addresses</td></tr>
<tr><td>ManageKnowledge</td><td>Manage Salesforce Knowledge</td></tr>
<tr><td>ManageKnowledgeImportExport</td><td>Manage Knowledge Article Import/Export</td></tr>
<tr><td>ManageLeads</td><td>Manage Leads</td></tr>
<tr><td>ManageLoginAccessPolicies</td><td>Manage Login Access Policies</td></tr>
<tr><td>ManageMobile</td><td>Manage Mobile Configurations</td></tr>
<tr><td>ManageNetworks</td><td>Create and Set Up Communities</td></tr>
<tr><td>ManagePasswordPolicies</td><td>Manage Password Policies</td></tr>
<tr><td>ManageProfilesets</td><td>Manage Profiles and Permission Sets</td></tr>
<tr><td>ManagePropositions</td><td>Manage Next Best Action Recommendations</td></tr>
<tr><td>ManagePvtRptsAndDashbds</td><td>Manage All Private Reports and Dashboards</td></tr>
<tr><td>ManageRecommendationStrategies</td><td>Manage Next Best Action Strategies</td></tr>
<tr><td>ManageReleaseUpdates</td><td>Manage Release Updates</td></tr>
<tr><td>ManageRemoteAccess</td><td>Manage Connected Apps</td></tr>
<tr><td>ManageReportsInPubFolders</td><td>Manage Reports in Public Folders</td></tr>
<tr><td>ManageRoles</td><td>Manage Roles</td></tr>
<tr><td>ManageSearchPromotionRules</td><td>Manage Promoted Search Terms</td></tr>
<tr><td>ManageSecurityCommandCenter</td><td>Manage Security Center</td></tr>
<tr><td>ManageSelfService</td><td>Manage Self-Service Portal</td></tr>
<tr><td>ManageSessionPermissionSets</td><td>Manage Session Permission Set Activations</td></tr>
<tr><td>ManageSharing</td><td>Manage Sharing</td></tr>
<tr><td>ManageSolutions</td><td>Manage Published Solutions</td></tr>
<tr><td>ManageSubscriptions</td><td>Manage Analytics Subscriptions</td></tr>
<tr><td>ManageSurveys</td><td>Manage Surveys</td></tr>
<tr><td>ManageSynonyms</td><td>Manage Synonyms</td></tr>
<tr><td>ManageTemplatedApp</td><td>Manage Analytics Templated Apps</td></tr>
<tr><td>ManageTwoFactor</td><td>Manage Multi-Factor Authentication in API</td></tr>
<tr><td>ManageUnlistedGroups</td><td>Manage Unlisted Groups</td></tr>
<tr><td>ManageUsers</td><td>Manage Users</td></tr>
<tr><td>ManageZapierIntegration</td><td>Manage your Zapier Integration</td></tr>
<tr><td>MassInlineEdit</td><td>Mass Edits from Lists</td></tr>
<tr><td>MergeTopics</td><td>Merge Topics</td></tr>
<tr><td>ModerateChatter</td><td>Moderate Chatter</td></tr>
<tr><td>ModerateNetworkUsers</td><td>Moderate Community Users</td></tr>
<tr><td>ModifyAllData</td><td>Modify All Data</td></tr>
<tr><td>ModifyDataClassification</td><td>Modify Data Classification</td></tr>
<tr><td>ModifyMetadata</td><td>Modify Metadata Through Metadata API Functions</td></tr>
<tr><td>ModifySecureAgents</td><td>Modify Secure Agents</td></tr>
<tr><td>NativeWebviewScrolling</td><td>Salesforce Mobile App: Native scrolling on webviews</td></tr>
<tr><td>NewReportBuilder</td><td>Report Builder</td></tr>
<tr><td>OptOutGeoLocationTracking</td><td>Exclude Technician from Geolocation Tracking</td></tr>
<tr><td>Packaging2</td><td>Create and Update Second-Generation Packages</td></tr>
<tr><td>Packaging2Delete</td><td>Delete Second-Generation Packages</td></tr>
<tr><td>PasswordNeverExpires</td><td>Password Never Expires</td></tr>
<tr><td>PreventClassicExperience</td><td>Hide Option to Switch to Salesforce Classic</td></tr>
<tr><td>PrivacyDataAccess</td><td>Allow user to access privacy data</td></tr>
<tr><td>PublishPackaging</td><td>Upload AppExchange Packages</td></tr>
<tr><td>QueryAllFiles</td><td>Query All Files</td></tr>
<tr><td>QuipMetricsAccess</td><td>Quip Metrics</td></tr>
<tr><td>QuipUserEngagementMetrics</td><td>Quip User Engagement Metrics</td></tr>
<tr><td>RecordVisibilityAPI</td><td>Enable RecordVisibility API</td></tr>
<tr><td>RemoveDirectMessageMembers</td><td>Remove People from Direct Messages</td></tr>
<tr><td>ResetPasswords</td><td>Reset User Passwords and Unlock Users</td></tr>
<tr><td>RunFlow</td><td>Run Flows</td></tr>
<tr><td>RunReports</td><td>Run Reports</td></tr>
<tr><td>SalesConsole</td><td>Sales Console</td></tr>
<tr><td>SandboxTestingInCommunityApp</td><td>Enables testing a sandbox community in the Mobile Publisher for Community Cloud app.</td></tr>
<tr><td>ScheduleReports</td><td>Schedule Reports</td></tr>
<tr><td>SelectFilesFromSalesforce</td><td>Select Files from Salesforce</td></tr>
<tr><td>SendAnnouncementEmails</td><td>Send announcement emails</td></tr>
<tr><td>SendCustomNotifications</td><td>Send Custom Notifications</td></tr>
<tr><td>SendExternalEmailAvailable</td><td>Send Email through External Email Service</td></tr>
<tr><td>SendSitRequests</td><td>Send Stay-in-Touch Requests</td></tr>
<tr><td>ShareInternalArticles</td><td>Share internal Knowledge articles externally</td></tr>
<tr><td>ShowCompanyNameAsUserBadge</td><td>Show Company Name as Community Role</td></tr>
<tr><td>SkipIdentityConfirmation</td><td>Skip Identity Confirmation at Login</td></tr>
<tr><td>SolutionImport</td><td>Import Solutions</td></tr>
<tr><td>SubmitMacrosAllowed</td><td>Manage Macros Users Can't Undo</td></tr>
<tr><td>SubscribeDashboardRolesGrps</td><td>Subscribe to Dashboards: Send to Groups and Roles</td></tr>
<tr><td>SubscribeDashboardToOtherUsers</td><td>Subscribe to Dashboards: Add Recipients</td></tr>
<tr><td>SubscribeReportRolesGrps</td><td>Subscribe to Reports: Send to Groups and Roles</td></tr>
<tr><td>SubscribeReportsRunAsUser</td><td>Subscribe to Reports: Set Running User</td></tr>
<tr><td>SubscribeReportToOtherUsers</td><td>Subscribe to Reports: Add Recipients</td></tr>
<tr><td>SubscribeToLightningDashboards</td><td>Subscribe to Dashboards</td></tr>
<tr><td>SubscribeToLightningReports</td><td>Subscribe to Reports</td></tr>
<tr><td>TraceXdsQueries</td><td>Access Tracer for External Data Sources</td></tr>
<tr><td>TransactionalEmailSend</td><td>Send Non-Commercial Email</td></tr>
<tr><td>TransferAnyCase</td><td>Transfer Cases</td></tr>
<tr><td>TransferAnyEntity</td><td>Transfer Record</td></tr>
<tr><td>TransferAnyLead</td><td>Transfer Leads</td></tr>
<tr><td>TwoFactorApi</td><td>Multi-Factor Authentication for API Logins</td></tr>
<tr><td>UseSubscriptionEmails</td><td>Use Subscription Emails</td></tr>
<tr><td>UseTeamReassignWizards</td><td>Use Team Reassignment Wizards</td></tr>
<tr><td>UseTemplatedApp</td><td>Use Analytics Templated Apps</td></tr>
<tr><td>UseWebLink</td><td>Allow Access to Customized Actions</td></tr>
<tr><td>ViewAllActivities</td><td>View All Activities</td></tr>
<tr><td>ViewAllCustomSettings</td><td>View All Custom Settings</td></tr>
<tr><td>ViewAllData</td><td>View All Data</td></tr>
<tr><td>ViewAllForeignKeyNames</td><td>View All Lookup Record Names</td></tr>
<tr><td>ViewAllProfiles</td><td>View All Profiles</td></tr>
<tr><td>ViewAllUsers</td><td>View All Users</td></tr>
<tr><td>ViewAnomalyEvents</td><td>View Threat Detection Events</td></tr>
<tr><td>ViewContent</td><td>View Content in Portals</td></tr>
<tr><td>ViewDataAssessment</td><td>Access to view Data Assessment</td></tr>
<tr><td>ViewDataCategories</td><td>View Data Categories in Setup</td></tr>
<tr><td>ViewDataLeakageEvents</td><td>View Real-Time Event Monitoring Data</td></tr>
<tr><td>ViewEncryptedData</td><td>View Encrypted Data</td></tr>
<tr><td>ViewEventLogFiles</td><td>View Event Log Files</td></tr>
<tr><td>ViewFlowUsageAndFlowEventData</td><td>View Flow Usage and Flow Event Data</td></tr>
<tr><td>ViewHealthCheck</td><td>View Health Check</td></tr>
<tr><td>ViewHelpLink</td><td>View Help Link</td></tr>
<tr><td>ViewMyTeamsDashboards</td><td>View My Team's Dashboards</td></tr>
<tr><td>ViewOnlyEmbeddedAppUser</td><td>Access to View-Only Licensed Templates and Apps</td></tr>
<tr><td>ViewPlatformEvents</td><td>View Login Forensics Events</td></tr>
<tr><td>ViewPrivateStaticResources</td><td>View Private Static Resources</td></tr>
<tr><td>ViewPublicDashboards</td><td>View Dashboards in Public Folders</td></tr>
<tr><td>ViewPublicReports</td><td>View Reports in Public Folders</td></tr>
<tr><td>ViewRoles</td><td>View Roles and Role Hierarchy</td></tr>
<tr><td>ViewSecurityCommandCenter</td><td>View Security Center pages</td></tr>
<tr><td>ViewSetup</td><td>View Setup and Configuration</td></tr>
<tr><td>ViewUserPII</td><td>View User Records with PII</td></tr>
<tr><td>WaveManagePrivateAssetsUser</td><td>Manage Analytics Private Assets</td></tr>
<tr><td>WaveTabularDownload</td><td>Download Analytics Data</td></tr>
<tr><td>WorkCalibrationUser</td><td>Enable WDC Calibration</td></tr>
<tr><td>WorkDotComUserPerm</td><td>Enable WDC</td></tr>
</tbody>
</table>
FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-19710377254233029142020-07-27T14:16:00.000+12:002020-07-27T14:22:04.320+12:00FuseIT SFDC Explorer 3.15.20209.3 - Summer '20<p>Another roundup of some of the changes to the <a href="http://www.fuseit.com/explorer">FuseIT SFDC Explorer</a> since the <a href="http://www.fishofprey.com/2020/02/fuseit-sfdc-explorer-313200081-winter-20.html">3.13.20008.1</a> release.</p>
<h2>Display the primary sObject type for a SOQL query in the executed units</h2>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnIZHWh7wqPrTB2WOodjlCQxz0RrAWoZvS4ahZ4kFiZ-yAbqpNUMJ94OogF7WeprX06p6pARfpZLHF2qVDcpTyOhGxkisB-vNjBVTeDBtIvc3NnaTny_hrctCCyBmHvsxCuAbkaixd_wGc/s1600/SoqlPrimarysObject.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnIZHWh7wqPrTB2WOodjlCQxz0RrAWoZvS4ahZ4kFiZ-yAbqpNUMJ94OogF7WeprX06p6pARfpZLHF2qVDcpTyOhGxkisB-vNjBVTeDBtIvc3NnaTny_hrctCCyBmHvsxCuAbkaixd_wGc/s1600/SoqlPrimarysObject.png" data-original-width="795" data-original-height="164" width="760" /></a>
<p>When looking at the "Show Executed Units" for a debug log that includes SOQL queries there is a new "SOQL Primary sObject" column. This makes it easier to sort the SOQL queries in the transaction by the sObject they were operating over.</p>
<p>There is also a new context menu option in the executed units area to filter the main log view to just the selected events.</p>
<p>Other changes include tracking Flow executed units and SOQL Total Rows metrics from debug logs.</li>
<h2>Add the MetadataComponentDependency API calls via the Bulk API 2.0</h2>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQYJFiJA1uonWG22MEJWIVJOwhCyWPxcHDaQgvL1eyfqw3BAnWkiEeXIbI9Jf6DhXfbbcUsrHI1aHGyAcSS41dl3yfteK6AbpeeR_UR2m_h1VpNB_G8z8XDEqEeJ63FT330NoxNyQBtHK_/s1600/DependencyGraph.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQYJFiJA1uonWG22MEJWIVJOwhCyWPxcHDaQgvL1eyfqw3BAnWkiEeXIbI9Jf6DhXfbbcUsrHI1aHGyAcSS41dl3yfteK6AbpeeR_UR2m_h1VpNB_G8z8XDEqEeJ63FT330NoxNyQBtHK_/s1600/DependencyGraph.png" data-original-width="1036" data-original-height="349" width="760" /></a>
<p>Previously the Metadata Dependencies tab was limited by the underlying MetadataComponentDependency API only supporting queries over 2,000 records in a single query. Switching to the bulk API expands this out to 100,000 dependency records.</p>
<p>There is also a new experimental graph format called "Microsoft Automatic Graph". This will use a built in graph layout tool. It is no where near as powerful as Gephi, but it is built in and allows you to gradually build the graph up. E.g. try starting with a single ID against "Where is it used" and then using the context menus to expand the graph incrementally.</p>
<h2>Rebuilt login and authentication controls.</h2>
<p>The various login and authentication controls that are displayed on app startup have a more consistent UI. For example, they have a consistent Login button.</p>
<h2 style="clear:both;">Other changes 3.15</h2>
<ul>
<li>Update SalesforceSession so that all APIs are working against v49.0 - Summer 20</li>
<li>Apex logging - add SOQL_EXECUTE_EXPLAIN Log event</li>
<li>Update SOQLResult column names when the defaultNamespace is defined. Includes first level relationship fields.</li>
<li>SFDCExplorer: Executed Units Context Menu to set Apex Log filter</li>
<li>SFDCExplorer: Show a message if there are issues showing an individual entity</li>
<li>SFDCExplorer: Support for flow log message types. Guard against debug logs with recursive search depth that is too great.</li>
<li>SFDCExplorer: Exception Handling when showing reports.</li>
<li>wsdl2apex: Warn if the schemaTypeName is missing.</li>
<li>SFDCExplorer: Expand Graph search ability</li>
<li>SFDCExplorer: Format VF_ log events in the timeline Handle deeply nested log structures to prevent stack overflows. </li>
<li>SFDCExplorer: Format byte size of log. Handling clicking a record ID in the log that doesn't exist in the current org. Option to format Callout requests in the debug log.</li>
<li>SFDCExplorer: Ensure the popup window that shows SOQL sub query results has a unique name so that the caching key is unique.</li>
<li>Tooling API. Check access to the DebugLevel metadata before attempting to query it.</li>
<li>SFDCExplorer: always prompt for directory to save metadata to.</li>
<li>Update All API versions to Spring 2020 (v48.0)</li>
<li>SFDCExplorer: Update .NET Framework version to 4.7.2 and add support for scaling to high DPI monitors.</li>
<li>SFDCExplorer: Update to cs31623 to allow for variation in the instanceUrl provided by the SFDX CLI</li>
<li>SFDCExplorer: Auto expand the test class search node when searching. Detect test classes in the queued state</li>
<li>SFDCExplorer: Export the results of a Bulk CSV load. This is useful if there where errors with the operation on individual records.</li>
<li>SFDCExplorer: Log metrics for callouts</li>
<li>Tooling API: Correct updating the log levels on TraceFlags</li>
</ul>FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-43195183093940072382020-05-20T20:18:00.000+12:002020-05-21T08:53:31.568+12:00Dreamforce 2019 Presentation - Reducing the Cost of Enforcing CRUD and FLS in the ESAPI<p>At Dreamforce <strike>this</strike> last year (2019) Chris Peterson and I gave a <a href="https://success.salesforce.com/apex/Sessions?eventId=a1Q3A000021ea1UUAQ#/session/a2q3A000002BJNlQAO">theater presentation</a> on combining the new Apex <code>Security.stripInaccessible</code> method with the existing <a href="https://github.com/forcedotcom/force-dot-com-esapi">ESAPI library</a> for enforcing Create, Retrieve, Update, Delete (CRUD) and field level security (FLS) in Apex.</p>
<p>Unfortunately the Dreamforce theater sessions weren't recorded in 2019 as they were in previous years 🤦♂️. To make up for that, below are the session slides. I'll also expand on the key points in this blog post. These will be my words rather than Chris's, although I'll try and cover most of the same content.</p>
<blockquote class="twitter-tweet"><p dir="ltr" lang="en">Slides from <a href="https://twitter.com/hashtag/DF19?src=hash&ref_src=twsrc%5Etfw">#DF19</a>: Reducing the cost of enforcing FLS & CRUD in the ESAPI <a href="https://t.co/T0Cl0MscJv">https://t.co/T0Cl0MscJv</a> with <a href="https://twitter.com/FishOfPrey?ref_src=twsrc%5Etfw">@FishOfPrey</a></p>— Chris Peterson (@ca_peterson) <a href="https://twitter.com/ca_peterson/status/1197355120729575424?ref_src=twsrc%5Etfw">November 21, 2019</a></blockquote> <script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script>
<h2>What is the ESAPI?</h2>
<p>The <b>ES</b> stands for <b>E</b>nterprise <b>S</b>ecurity. And the <b>API</b>... Well, hopefully you know what an API is.</p>
<p>The <a href="https://github.com/forcedotcom/force-dot-com-esapi">Salesforce ESAPI</a> is a port of a Java library created by OWASP (Open Web Application Security Project).</p>
<p>To address why you would want it in your Salesforce org, here is a quote from the <a href="https://owasp.org/www-project-enterprise-security-api/">OWASP ESAPI project</a> page:</p>
<blockquote>
The ESAPI libraries are designed to make it easier for programmers to retrofit security into existing applications. The ESAPI libraries also serve as a solid foundation for new development.
</blockquote>
<p>These seem like noble goals. We want to improve the security of existing applications and implement newer applications with the same level of security from the start.</p>
<p>The three core areas that the Salesforce ESAPI addresses are:</p>
<ol>
<li><a href="https://github.com/forcedotcom/force-dot-com-esapi#input-validation">Input Validation</a> - is a given string a valid date? Is it a valid credit card number? A valid redirection URL?
<ul>
<li>E.g. ESAPI.validator.SFDC_isValidDate</li>
</ul>
</li>
<li><a href="https://github.com/forcedotcom/force-dot-com-esapi#output-encoding">Output Encoding</a> - is is safe to render the content back to the users browser via HTML?
<ul>
<li>E.g. ESAPI.encoder.SFDC_URLENCODE</li>
</ul>
</li>
<li><a href="https://github.com/forcedotcom/force-dot-com-esapi#access-control">Access Control</a> - enforce the built in access control mechanisms: CRUD, FLS, and Sharing.
<ul>
<li>insertAsUser/updateAsUser</li>
<li>DML on a limited set of fields</li>
<li>Override sharing for a single DML operation</li>
</ul>
</li>
</ol>
<h2>(Re) Introducing the ESAPI</h2>
<p>Salesforce originally released their version of the ESAPI library in 2010. In 2016 they added the new <code>ESAPI.encoder.SFDC_BASE64_URLENCODE</code> method. Other than that it was stalled for any maintenance or new development.</p>
<p>In 2019 Chris Peterson and Jake Meredith from Salesforce took ownership of the Github repo. Even better, they are accepting pull requests.</p>
<p>One of the first steps in rejuvenating the repo was to <a href="https://github.com/forcedotcom/force-dot-com-esapi/pull/14">increase the built in code coverage from 54% to 93%</a> on the security specific test methods. And, perhaps more importantly, add a number of meaningful assertions and negative test cases along the way. Overall project test coverage is now up by 39%.</p>
<p>One of the particular challenges with this was scripting out of the box test cases using only the built in Profiles and sObjects. The test cases needed to be portable to any org, so they couldn't rely on a specific custom Profile existing. At the time the "Read Only" profile was the most restrictive system profile available. Going forward I might revisit this with the still to GA Minimum Access profile.</p>
<blockquote class="twitter-tweet"><p dir="ltr" lang="en">There is a new Minimum Access profile in <a href="https://twitter.com/hashtag/salesforce?src=hash&ref_src=twsrc%5Etfw">#salesforce</a> <a href="https://twitter.com/hashtag/summer20?src=hash&ref_src=twsrc%5Etfw">#summer20</a>.<br />It may seem like a small thing, but if you've every tried to full control access with permissions sets or had to create such a profile yourself you will know what a useful time saver this will be.<a href="https://twitter.com/hashtag/Summer20Treasure?src=hash&ref_src=twsrc%5Etfw">#Summer20Treasure</a> <a href="https://t.co/SWBMqfSxM3">pic.twitter.com/SWBMqfSxM3</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1254955293458350080?ref_src=twsrc%5Etfw">April 28, 2020</a></blockquote> <script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script>
<p>With the better test coverage in place it was then possible to overhaul how the field and object level security was enforced. More on that later...</p>
<h2>A Recap of the Security.stripInaccessible() method</h2>
<p>The <a href="https://releasenotes.docs.salesforce.com/en-us/spring20/release-notes/rn_apex_Security_stripInaccessible_GA.htm">Spring '20 release</a> included the GA version of the new <code>Security.stripInaccessible</code> method.</p>
<p>This new method provides a streamlined way to check both field and object level data permissions for the following <a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_enum_System_AccessType.htm">access types</a>:</p>
<ul>
<li>AccessType.READABLE - Check the fields of an sObject for read access.</li>
<li>AccessType.CREATABLE - Check the fields of an sObject for create access.</li>
<li>AccessType.UPDATABLE - Check the fields of an sObject for update access.</li>
<li>AccessType.UPSERTABLE - Check the fields of an sObject for insert and update access.</li>
</ul>
<h2>The SObjectAccessDecision Object</h2>
<p>After calling stringInaccessible() an <a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_class_System_SObjectAccessDecision.htm"><code>SObjectAccessDecision</code></a> object is returned. This provides a number of helpful methods.</p>
<p><code>getRecords()</code> provides a new <code>List<SObject></code> that has all the inaccessible fields removed. These are also detached from the source sObjects.</p>
<p>Two additional methods <code>getModifiedIndexes()</code> and <code>getRemovedFields()</code> provide details about which records and specific fields were modified.</p>
<h2>How it works in practice to enforce security requirements</h2>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPcn_etl4QaHjvwUDxfrL_8KdXj2crdKGHXNWeOKJWFlXIxEh52T-UaYsS_8As-wCRrXFAURMBoHPUZ6lzD5RyKmNSkzARimmYkeYDEIpTIfTaaVNrW4ImfbUnSryactUtaVg7493CEPC5/s1600/DF19+-+ESAPI+Talk+%2528Reducing+the+cost+of+enforcing+FLS+%2526+CRUD+in+the+ESAPI%2529.pptx.png"><img border="0" data-original-height="719" data-original-width="1279" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPcn_etl4QaHjvwUDxfrL_8KdXj2crdKGHXNWeOKJWFlXIxEh52T-UaYsS_8As-wCRrXFAURMBoHPUZ6lzD5RyKmNSkzARimmYkeYDEIpTIfTaaVNrW4ImfbUnSryactUtaVg7493CEPC5/s800/DF19+-+ESAPI+Talk+%2528Reducing+the+cost+of+enforcing+FLS+%2526+CRUD+in+the+ESAPI%2529.pptx.png" width="700" /></a>
<p>Using the newer stringInaccessible method has a number of advantages. It will cover all possible sObject field types. It will check relationship fields, including nested relationships. Sub-queries and polymorphic lookups are also covered.</p>
<p>The example in the image above shows a new Opportunity for "Appy's App" that was generated in the trusted system mode. As such, it could set the custom Standing__c and Value__c fields. This Opportunity is then passed through stringInaccessible with the <code>AccessType.CREATABLE</code> parameter. This does all the hard work for us of checking the users Profiles, Permission Sets, the Permission Set groups, the muting permission sets, etc... The output Opportunity has the fields that the user doesn't have create access to completely removed. The stripped fields aren't null: they're really undefined. This is important when it comes to subsequent DML as we don't want to inadvertently clear fields out.</p>
<p>Other advantages:</p>
<ul>
<li>It's particularly useful when handling untrusted input (like from JavaScript controllers)</li>
<li>It's also great for gracefully degrading UI experiences like SFDC does natively</li>
</ul>
<h2>Example walk through code the changes to the ESAPI</h2>
<p>The video shows the core structural changes that were made to the ESAPI methods to use the new methods.</p>
<iframe allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/oboNEYYp3GY" width="560"></iframe>
<h2>Measuring the Performance changes - Methodology</h2>
<p>Beyond enforcing the security requirements the next important consideration is changes to CPU Limit usage and Heap usage. Usually you trade more CPU for less Heap or vice versa. If we can cut both down we are doing well!</p>
<p>The general goal is always to see equal of better performance while enforcing the same security requirements. There may be some tradeoffs in performance made, but the security can't be compromised on. The coverage and assertions from the automated tests ensure we are still enforcing the same security requirements.</p>
<p>The performance differences in terms of Apex limits were measured using <a href="https://github.com/FishOfPrey/force-dot-com-esapi-performance">Test harness classes</a> and Adrian Larsons <a href="https://github.com/apexlarson/LimitsProfiler">LimitsProfiler</a> framework. Performing multiple runs between the current/baseline implementation and the new version using the stripping methods allows the relative changes in limits to be measured.</p>
<script src="https://gist.github.com/FishOfPrey/3fc267439195e50f788bfec63ee4b888.js"></script>
<p>During the testing it was important to have the debug logging completely off as it would otherwise affect the outcomes.</p>
<p>The testing below was done in ALL_OR_NONE mode. This is more demanding than the alternative BEST_EFFORT mode as it requires per field level checks.</p>
<p>To allow for the limits testing framework to repeatedly insert multiple records Savepoints were used as part of the setup and teardown steps. This prevented hitting the storage limits while still measuring the performance differences in the ESAPI.</p>
<h2>Measured results for bulk inserting Contacts</h2>
<iframe width="560" height="315" src="https://www.youtube.com/embed/cjXo9Lg5XNg" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<p>The performance difference can vary greatly based on scenario:</p>
<ul>
<li>There is negligible performance difference when checking object CRUD permissions. Note, the Apex ESAPI is still enforcing against the sObject Schema.SObjectType until 224 (Spring `20) with the fix.</li>
<li>There is a significant performance difference if there are a large number of requested fields that aren’t set on all the sObjects. <!--Depends if stripping proceeds sobject copying or not.--></li>
</ul>
<p>Measured improvements on <a href="https://github.com/FishOfPrey/force-dot-com-esapi-performance/blob/master/force-app/main/default/classes/Profilers.cls#L65">25 iterations inserting 200 Contacts. 33 Standard fields</a>
</p>
<ul>
<li>25% Less CPU usage</li>
<li>18.6% Less Heap usage</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUuhhlGIQJuTSKpQkpdtGYX4VWx5kIWC6EkeXP1EyR5nwNw1gKkU-cPcsrbwneJDxRDUaOPyl0zZVrQWR9N1ybSWRvtH2rEwrAMSnlhYNerLOjreCJM2JqsUZ2tC2MPOlm5RLlSULp0Ni9/s1600/StockESAPI.png" style="margin-left: 1em; margin-right: 1em;">
<img border="0" data-original-height="646" data-original-width="1070" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUuhhlGIQJuTSKpQkpdtGYX4VWx5kIWC6EkeXP1EyR5nwNw1gKkU-cPcsrbwneJDxRDUaOPyl0zZVrQWR9N1ybSWRvtH2rEwrAMSnlhYNerLOjreCJM2JqsUZ2tC2MPOlm5RLlSULp0Ni9/s800/StockESAPI.png" width="760" />
</a>
</div>
<h2>Links and Resource</h2>
<ul>
<li><a href="https://sfdc.co/apex-esapi">ESAPI on GitHub</a> </li>
<li><a href="https://sfdc.co/apex-strip-doc">Security.stripInaccessible developer docs</a></li>
<li><a href="https://speakerdeck.com/ca_peterson/apex-object-and-field-security-made-easy">TDX19 Deeper Dive on Apex FLS/CRUD</a></li>
<li><a href="https://developer.salesforce.com/blogs/2020/01/learn-moar-in-spring-20-with-field-level-security-in-apex.html">Learn MOAR in Spring ’20 with Field Level Security in Apex</a></li>
</ul>
FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-81177051825563080762020-02-13T14:27:00.000+13:002020-02-13T14:32:50.704+13:00FuseIT SFDC Explorer 3.13.20008.1 - Winter '20<p>Another roundup of some of the changes to the <a href="http://www.fuseit.com/explorer">FuseIT SFDC Explorer</a> since the <a href="http://www.fishofprey.com/2019/06/fuseit-sfdc-explorer-312191751-summer-19.html">3.12.19175.1</a> release.</p>
<h2 style="clear:both;">Redesigned Apex Tests selector</h2>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQ5BIxPpa-tBwi7y_m44fEY4Lc6stTmR2Xsm1wwi7V6s4yomkpAPH3eXmSzFbBNy2BlsGFQdmb7DZP4G4i3UHNeIXh1YROw-3CMvJB9u6JRS0_aDk5HhcbRKzGsipVv15VpP_ZgaV0FE0C/s1600/TestBreakDown.PNG" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQ5BIxPpa-tBwi7y_m44fEY4Lc6stTmR2Xsm1wwi7V6s4yomkpAPH3eXmSzFbBNy2BlsGFQdmb7DZP4G4i3UHNeIXh1YROw-3CMvJB9u6JRS0_aDk5HhcbRKzGsipVv15VpP_ZgaV0FE0C/s1600/TestBreakDown.PNG" data-original-width="325" data-original-height="125" /></a>
<p>The Apex test selection control has been reworked to include a top level node for the last known state of each test method. This allows you to monitor the accumulated test results from a single location. If you redeploy one of the test cases in question it will reset to an unknown status.</p>
<h2 style="clear:both;">Updates to the Debug Log Executed Units</h2>
<p>In the <a href="https://www.fishofprey.com/2019/06/fuseit-sfdc-explorer-312191751-summer-19.html">last release</a> I put in the first version of the Executed Units control. This release builds on that.</p>
<p>It is now possible to mix and match the different log types. So you can focus on, for example, just the SOQL queries.</p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirZYyuboYHw8aR26Sh1q8FQ1aL67cEm_ThgIqVmLlrAGGj_QVwocp3mTCdYvD-ze9dAffyZDOGCwZa1ZNLxy-PgZONDqeL59lZM97PviaW4wnhTGC9Z-zNYmF1han_MM5H2lOqCUxT63Q3/s1600/ExecutedUnits.PNG" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirZYyuboYHw8aR26Sh1q8FQ1aL67cEm_ThgIqVmLlrAGGj_QVwocp3mTCdYvD-ze9dAffyZDOGCwZa1ZNLxy-PgZONDqeL59lZM97PviaW4wnhTGC9Z-zNYmF1han_MM5H2lOqCUxT63Q3/s1600/ExecutedUnits.PNG" data-original-width="597" data-original-height="231" /></a>
<p>The same toolstrip includes a button to export the executed units data.</p>
<!--
* [cs32196] SFDCExplorer: Track debug log metrics by selected type. Includes within namespace SOQL Query limit usage
* [cs32156] SFDCExplorer: Expand the Executed Units Control out to different log types. Option to Export the findings
* [cs31815] SFDCExplorer: Cleanup Executed Units control
-->
<h2 style="clear:both;">Smaller generated Wsdl2Apex classes</h2>
<p>If you've ever looked closely at the Apex classes that Wsdl2Apex generates you'll notice a recurring string - the namespace of the the root element. Depending on the WSDL it's not uncommon for this same string to be repeated thousands of times in the generated Apex class. This update will now generate a single <code>static final</code> to handle the repeated usages.</p>
<!--* [cs32000] Wsdl2Apex generate the common namespaces as constants on the root classes. -->
<h2 style="clear:both;">New controls for exploring Execution overlays, including heap dumps</h2>
<p>The developer console currently provides a viewer for <a href="https://developer.salesforce.com/docs/atlas.en-us.api_tooling.meta/api_tooling/tooling_api_objects_apexexecutionoverlayresult.htm">execution overlay output </a>created by a <a href="https://developer.salesforce.com/docs/atlas.en-us.api_tooling.meta/api_tooling/tooling_api_objects_apexexecutionoverlayaction.htm"><code>ApexExecutionOverlayAction</code></a> record. This includes the Heap Dump, which has all sorts of interesting details about the data stored in heap/memory for the transaction at the the point of time the overlay was captured.</p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8X6F12Mgp0cUfNt7Gsu9cigUzYpOi3Sc4_xt8JWtdtETP1x3vToh1vYGWAGQEHehULLQqKZU5sWel_rIylrHukpwjdTmOukD2UqjaiUrVB4FvKuptrCJMFKu87VIJM8DtWVlpdjCcpWb5/s1600/HeapViewer.PNG" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8X6F12Mgp0cUfNt7Gsu9cigUzYpOi3Sc4_xt8JWtdtETP1x3vToh1vYGWAGQEHehULLQqKZU5sWel_rIylrHukpwjdTmOukD2UqjaiUrVB4FvKuptrCJMFKu87VIJM8DtWVlpdjCcpWb5/s400/HeapViewer.PNG" width="400" height="376" data-original-width="649" data-original-height="610" /></a>
<p>Right now it mostly just replicates the existing developer console functionality and allows browsing the stored objects by type.</p>
<h2 style="clear:both;">Other changes 3.13</h2>
<ul>
<li> [cs32197] SFDCExplorer: Option to save a debug log directly to disk.</li>
<li> [cs32152] SFDCExplorer: Auto add metadata files when adding package components. Update display of Metadata Deploy results.</li>
<li> [cs32150] SFDCExplorer: Allow the target save directory to be specified when doing an unpackaged metadata export (if the working directory isn't accessible)</li>
<li> [cs32149] SFDCExplorer: Use internal list of known key prefixes with the Entity Explorer</li>
<li> [cs32148] SFDCExplorer: Option on running SOQL queries to include deleted rows</li>
<li> [cs32003] Update to Winter '20 release. v47.0 </li>
<li> [cs31838] Wsdl2Apex: Handle an operation binding with no output. Raising a warning for a missing portType rather than an exception. </li>
<li> [cs31820] SFDCExplorer: Hide JavaScript errors during OAuth login </li>
</ul>
FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-21768706777703169922019-11-27T21:24:00.000+13:002019-12-11T08:02:29.485+13:00Dreamforce 2019 Roundup / Summary<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQAhxOuFbmv5PslPOsQujxGk5TZpsdsKV-1-x0fC9BGLwYqzwgSEDKy-uGGxQtyLbVNpEr8g3BQZbOSPQWl_HYuCILSuSp4WojjoQXuDtS-Rh5osyG1jRAjE_vJrsdrjG1qO6RSZPyGRTu/s1600/TitleSlide.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQAhxOuFbmv5PslPOsQujxGk5TZpsdsKV-1-x0fC9BGLwYqzwgSEDKy-uGGxQtyLbVNpEr8g3BQZbOSPQWl_HYuCILSuSp4WojjoQXuDtS-Rh5osyG1jRAjE_vJrsdrjG1qO6RSZPyGRTu/s800/TitleSlide.png" width="640" height="294" data-original-width="1600" data-original-height="736" /></a></div>
<a href="https://github.com/afawcett/df18-dx-demo"></a>
<p>The recap for this Dreamforce is going to come across as a bit of a photo journal as I go back through my phones timeline to piece back together what I got up to. Somehow, even on my 6th time attending this conference things still went past at a frantic pace.</p>
<h2 style="clear: both;">Table of Contents</h2>
<ol>
<li><a href="#preconference">Preconference</a></li>
<li><a href="#day1">Day One</a>
<ul>
<li>Main Keynote</li>
<li>Meet the Developers</li>
</ul>
</li>
<li><a href="#day2">Day Two</a>
<ul>
<li>Developer Keynote</li>
<li>My Presentation</li>
<li>True to the Core</li>
<li>Dreamfest</li>
</ul>
</li>
<li><a href="#day3">Day Three</a>
<ul>
</ul>
</li>
<li><a href="#day4">Day Four</a>
<!--<ul>
<li>Mulesoft</li>
</ul>-->
</li>
</ol>
<hr/>
<h2 style="clear: both;" id="preconference">Preconference</h2>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Cycled from Hyde St to Point Bonita lighthouse and back today. The trip up to the Marin Headlands Vista Pt was well worth. <a href="https://t.co/jtuEKAiioI">pic.twitter.com/jtuEKAiioI</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1196228914600742912?ref_src=twsrc%5Etfw">November 18, 2019</a></blockquote>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Packing a few spare hoodies for <a href="https://twitter.com/hashtag/DF19?src=hash&ref_src=twsrc%5Etfw">#DF19</a>, just in case. <a href="https://t.co/SQ1YMj4zrJ">pic.twitter.com/SQ1YMj4zrJ</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1195482569950629889?ref_src=twsrc%5Etfw">November 15, 2019</a></blockquote>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">This the hoodie to chase at <a href="https://twitter.com/hashtag/DF19?src=hash&ref_src=twsrc%5Etfw">#DF19</a> <a href="https://t.co/kBYWQrSYNF">pic.twitter.com/kBYWQrSYNF</a></p>— 𝐂𝐚𝐫𝐥𝐨𝐬 𝐒𝐢𝐪𝐮𝐞𝐢𝐫𝐚 (@akaCarioca) <a href="https://twitter.com/akaCarioca/status/1196222386942562304?ref_src=twsrc%5Etfw">November 18, 2019</a></blockquote>
<div class="separator" style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgY1LKfFcfM7VVBm6Pe4nyHRUhCYoI01xn_-FAy3IUVCMpMZtWzvlceOWFU75Il_qRSHdvfkzrAJ-VVAwx4qUk5osNkJ8WQxZzYC7jhyphenhyphen00t8QxSXe-2LEEremPyiPoU2Or-ndYFofx-4j2k/s1600/20191118_190940.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgY1LKfFcfM7VVBm6Pe4nyHRUhCYoI01xn_-FAy3IUVCMpMZtWzvlceOWFU75Il_qRSHdvfkzrAJ-VVAwx4qUk5osNkJ8WQxZzYC7jhyphenhyphen00t8QxSXe-2LEEremPyiPoU2Or-ndYFofx-4j2k/s400/20191118_190940.jpg" width="300" height="400" data-original-width="866" data-original-height="1154" /></a>
</div>
<p>A visit to the Salesforce Tower for the Tooling Partner meeting and the Dreamforce speaker party.</p>
<h2 id="day1" style="clear: both;">Day One - 20th Nov</h2>
<h3>Main keynote</h3>
<ul>
<li><a href="https://www.salesforce.com/blog/2018/09/what-is-salesforce-customer-360.html">Customer 360</a> - A way to bring all the siloed data about a customer together. </li>
<li><blockquote class="twitter-tweet"><p lang="en" dir="ltr">Prototype <a href="https://twitter.com/hashtag/Salesforce?src=hash&ref_src=twsrc%5Etfw">#Salesforce</a> Einstein voice assistant based on Alexa hardware. <a href="https://twitter.com/hashtag/DF19?src=hash&ref_src=twsrc%5Etfw">#DF19</a> <a href="https://t.co/HDjsySkkXM">pic.twitter.com/HDjsySkkXM</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1196871155396702208?ref_src=twsrc%5Etfw">November 19, 2019</a></blockquote> </li>
<li><blockquote class="twitter-tweet"><p lang="en" dir="ltr">Step 3: Create a dense point cloud from the point matches and triangulation results.<br>Step 4: Create a surface from the results of Step 3.<br>Step 5: Print 3D model.<br>Step 6: ???<a href="https://twitter.com/hashtag/photogrammetry?src=hash&ref_src=twsrc%5Etfw">#photogrammetry</a> <a href="https://twitter.com/hashtag/HeyEinstein?src=hash&ref_src=twsrc%5Etfw">#HeyEinstein</a> <a href="https://twitter.com/hashtag/DF19?src=hash&ref_src=twsrc%5Etfw">#DF19</a> <a href="https://t.co/9BHz7hvQ1S">pic.twitter.com/9BHz7hvQ1S</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1199255585453043714?ref_src=twsrc%5Etfw">November 26, 2019</a></blockquote> </li>
</ul>
<h3>Meet the Developers</h3>
<ul>
<li>This session wasn't recorded, but there were a number of good questions raised. I asked about possible ways to streamline the reporting and monitoring of GACKs.</li>
</ul>
<h3><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1UUAQ#/session/a2q3A000002BJlMQAW">Platform Cache: Why Implementing Platform Cache Is Just Like Riding a Bike</a></h3>
<ul>
<li><blockquote class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://twitter.com/hashtag/Dreamforce?src=hash&ref_src=twsrc%5Etfw">#Dreamforce</a> is all about big announcements-proud to add my team’s name to the list at <a href="https://twitter.com/hashtag/DF19?src=hash&ref_src=twsrc%5Etfw">#DF19</a>.<br><br>Everyone should be using in-memory cache in their scalable apps. To show how passionate we are about this design, we’re giving our managed platform cache away to <a href="https://twitter.com/hashtag/Salesforce?src=hash&ref_src=twsrc%5Etfw">#Salesforce</a> customers. <a href="https://t.co/HU5NNSswlI">pic.twitter.com/HU5NNSswlI</a></p>— Matthew Parin (@mattparin) <a href="https://twitter.com/mattparin/status/1197132866536251392?ref_src=twsrc%5Etfw">November 20, 2019</a></blockquote></li>
</ul>
<h2 id="day2">Day Two - 21st Nov</h2>
<h3><a href="https://developer.salesforce.com/blogs/2019/11/df19-developer-keynote-highlights.html">Developer Keynote</a></h3>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbGjf8_P_kF5fijBSaKkyYXs7VmyvcETBs8b8_hCZjbddIh6wZVWS8kSpH4kXVBaZ1JprGn8-R5sd_58YjsR71ZRMG5nqAt8mUeXXdn_VlP-oQedm4S0jYdEsC47579XGZdVi_AZFDH5-V/s1600/20191120_093721.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbGjf8_P_kF5fijBSaKkyYXs7VmyvcETBs8b8_hCZjbddIh6wZVWS8kSpH4kXVBaZ1JprGn8-R5sd_58YjsR71ZRMG5nqAt8mUeXXdn_VlP-oQedm4S0jYdEsC47579XGZdVi_AZFDH5-V/s640/20191120_093721.jpg" width="640" height="205" data-original-width="1600" data-original-height="512" /></a></div>
<ul>
<li>Evergreen was certainly a core part of the keynote and will introduce the ability to create event-driven apps composed of functions and microservices. Targeting support for Node.js, Java, and Apex at launch (safe harbor). <br/>Detailed blog post <a href="https://sforce.co/35nWA0i">Evergreen: Serverless Functions & Compute for Customer 360 Platform</a>. <br/>Sign up for the pilot - <a href="https://sfdc.co/evergreenSignup">https://sfdc.co/evergreenSignup</a>.
<blockquote class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://twitter.com/hashtag/DF19?src=hash&ref_src=twsrc%5Etfw">#DF19</a> developer keynote introducing Evergreen for different types or processing load. And it is packagable by ISVs. <a href="https://t.co/irtm5HDBmj">pic.twitter.com/irtm5HDBmj</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1197201399592804352?ref_src=twsrc%5Etfw">November 20, 2019</a></blockquote></li>
<li><a href="https://twitter.com/FishOfPrey/status/1197204892445622272">Salesforce API Portal</a>. An expanded version of the current <a href="https://t.co/Hxu4MUVWVV?amp=1">API Explorer</a> which will include more APIs and mock responses.</li>
<li>Local development of LWC - in beta</li>
<li><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuXN8Azm86Q7qplsjmLgZlyQp84bAzL9uqJaztfwh0aacrscvSXLdWymc-rYIlWczZ7_tlEDGKf6t-GWuOL8n7mD4YJFXJOBDmu5cKHnhiUNLpA7mEYCv74pcYvQ_STQTWotFHw6FKFLje/s1600/SandboxesAndMasking.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuXN8Azm86Q7qplsjmLgZlyQp84bAzL9uqJaztfwh0aacrscvSXLdWymc-rYIlWczZ7_tlEDGKf6t-GWuOL8n7mD4YJFXJOBDmu5cKHnhiUNLpA7mEYCv74pcYvQ_STQTWotFHw6FKFLje/s320/SandboxesAndMasking.png" width="320" height="180" data-original-width="1195" data-original-height="672" /></a></div>Data Masking for sandboxes - remove sensitive customer data from sandboxes.</li>
<li><a href="http://sforce.co/df19-devtrailmix">Trailmix for the Developer keynote</a></li>
<li>YouTube - <a href="https://www.youtube.com/watch?v=cFDbam9FQnU">Dreamforce 2019 Developer Keynote: Continuous Innovation with the Customer 360 Platform</a></li>
</ul>
<h3 style="clear: both;"><a href="https://www.google.com/url?q=https://success.salesforce.com/apex/m_Sessions?eventId%3Da1Q3A000021ea1UUAQ%23/session/a2q3A000002BJNlQAO&sa=D&usd=2&usg=AOvVaw00v7GE0CkCdTAjGQgxsZLu">Reducing the Cost of Enforcing CRUD and FLS in the ESAPI</a></h3>
<ul>
<li>Presentation on updates to the ESAPI by Chris and myself</li>
</ul>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Slides from <a href="https://twitter.com/hashtag/DF19?src=hash&ref_src=twsrc%5Etfw">#DF19</a>: Reducing the cost of enforcing FLS & CRUD in the ESAPI <a href="https://t.co/T0Cl0MscJv">https://t.co/T0Cl0MscJv</a> with <a href="https://twitter.com/FishOfPrey?ref_src=twsrc%5Etfw">@FishOfPrey</a></p>— Chris Peterson (@ca_peterson) <a href="https://twitter.com/ca_peterson/status/1197355120729575424?ref_src=twsrc%5Etfw">November 21, 2019</a></blockquote>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Around lunch I told you to write less code and leverage proven Open-source to make your code cleaner and more agile. To check CRUD & FLS from today there is only ONE tool that will bring you through sec review like a charm. StripInaccessible included! <a href="https://t.co/HhsFHPTCIl">pic.twitter.com/HhsFHPTCIl</a></p>— Robert Sösemann (@rsoesemann) <a href="https://twitter.com/rsoesemann/status/1197305689812525056?ref_src=twsrc%5Etfw">November 21, 2019</a></blockquote>
<h3>True to the Core</h3>
<ul>
<li>YouTube: <a href="https://www.youtube.com/watch?v=Wpveu2Ef8-Q">True to the Core with Parker Harris and Bret Taylor</a></li>
</ul>
<h3><a href="https://www.google.com/url?q=https://success.salesforce.com/apex/m_Sessions?eventId%3Da1Q3A000021ea1UUAQ%23/session/a2q3A000002BJWsQAO&sa=D&usd=2&usg=AOvVaw1mdtonW89RpCSvZmiY3xEd">Entity Interfaces</a></h3>
<ul>
<li>Survey link for registering interest in Entity Interfaces - <a href="https://sfdc.co/ImplementThis">https://sfdc.co/ImplementThis</a></li>
</ul>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Entity interfaces to allow for different mappings of object storage to a consistent interface. <a href="https://t.co/zfvZkIOu96">pic.twitter.com/zfvZkIOu96</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1197313071124926464?ref_src=twsrc%5Etfw">November 21, 2019</a></blockquote>
<h3>Dreamfest</h3>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqFTML8qT2ARbb-nAEm7JUmh0IYdlgejbHXM0uAjr_kGiOo0cAvABhVDSHr16-kqEHeNn-KmgXQGdM4qu0b4heFIlzd-22N96-URNJg3qeGMbtrsOhuqHCThcWvymP0EXgSTwtjZTBnXd2/s1600/20191120_221228.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqFTML8qT2ARbb-nAEm7JUmh0IYdlgejbHXM0uAjr_kGiOo0cAvABhVDSHr16-kqEHeNn-KmgXQGdM4qu0b4heFIlzd-22N96-URNJg3qeGMbtrsOhuqHCThcWvymP0EXgSTwtjZTBnXd2/s640/20191120_221228.jpg" width="640" height="263" data-original-width="1600" data-original-height="657" /></a></div>
<ul>
<li>Bands this year were Beck and Fleetwood Mac</li>
</ul>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Cool. A band playing the greatest hits from Guardians of the Galaxy.<a href="https://twitter.com/hashtag/DF19?src=hash&ref_src=twsrc%5Etfw">#DF19</a> <a href="https://t.co/j9WL2sjmKU">pic.twitter.com/j9WL2sjmKU</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1197386161515159552?ref_src=twsrc%5Etfw">November 21, 2019</a></blockquote>
<h2 style="clear: both;" id="day3">Day Three - 22nd</h2>
<h3 style="clear: both;"><a href="https://www.google.com/url?q=https://success.salesforce.com/apex/m_Sessions?eventId%3Da1Q3A000021ea1UUAQ%23/session/a2q3A000002BJQBQA4&sa=D&usd=2&usg=AOvVaw3Ytb3dDwH7DVRHbBGabQ7Z">Open conversation about DX</a></h3>
<ul>
<li>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Some of the current challenges with SFDX. Outlined in the open conversation about DX session.<a href="https://twitter.com/hashtag/DF19?src=hash&ref_src=twsrc%5Etfw">#DF19</a> <a href="https://t.co/WJtqGKY8wo">pic.twitter.com/WJtqGKY8wo</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1197622990424272896?ref_src=twsrc%5Etfw">November 21, 2019</a></blockquote>
</li>
<li>Use <a href="https://twitter.com/search?q=%23TalkDX">#TalkDX</a> on twitter or <a href="https://sforce.co/talk-dx">https://sforce.co/talk-dx</a></li>
</ul>
<h3><a href="https://www.google.com/url?q=https://success.salesforce.com/apex/m_Sessions?eventId%3Da1Q3A000021ea1UUAQ%23/session/a2q3A000002BJNbQAO&sa=D&usd=2&usg=AOvVaw1wws9ZxrCIEYVRq-0mWSxI">Everything You Need to Know on Apex Debuggers</a></h3>
<h3>Quip and Into the blue parties</h3>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2Ob15r_rHY6JAajxsug2e35m_dKZ-dY2wHgg-QpAcK9toU07aB5ojzLSQT84sEqxi3IvtTHO-vrL7lAgmU-v92bJrkP5MZmWBo9WjZMGnLm8eDcJ-EZY55_2k6Eba4qmhjCkDutEC4jfC/s1600/20191121_211710.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2Ob15r_rHY6JAajxsug2e35m_dKZ-dY2wHgg-QpAcK9toU07aB5ojzLSQT84sEqxi3IvtTHO-vrL7lAgmU-v92bJrkP5MZmWBo9WjZMGnLm8eDcJ-EZY55_2k6Eba4qmhjCkDutEC4jfC/s320/20191121_211710.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a></div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnzPj3gdoGWDNyF0wWme5Wavk63HmPWxUpjoMltu1K3lgfPUKCdIkO067_bw_hqioZ29BI_MAylCmQ3Ir4VnSfwrEFfG_8EKRCjU9Ovm6Jj3nrEkBnFh6ZRHEWxwkR0-7vQXTj1H6c7Fz-/s1600/20191121_221915.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnzPj3gdoGWDNyF0wWme5Wavk63HmPWxUpjoMltu1K3lgfPUKCdIkO067_bw_hqioZ29BI_MAylCmQ3Ir4VnSfwrEFfG_8EKRCjU9Ovm6Jj3nrEkBnFh6ZRHEWxwkR0-7vQXTj1H6c7Fz-/s320/20191121_221915.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a></div>
<h2 style="clear: both;" id="day4">Day 4 - 23rd</h2>
<h3><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1UUAQ#/session/a2q3A000002BJO9QAO">Salesforce Evergreen & Evergreen Functions: Evented Serverless Consumer Apps (2)</a></h3>
<ul>
<li></li>
</ul>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpNarubgQKrtnxC8c16qvXeRYbaPb57cmnl_RyldMPaH1k8IwQjT1KsQpn1Z-u_IAtnJL7_-u0tjyjOXRTHkiGaiCYSdqr68PuhQcX69ZiTrRXZEd6wzQWTMyyFOvzkVJJNdgSldh4Gtdd/s1600/20191122_121858.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpNarubgQKrtnxC8c16qvXeRYbaPb57cmnl_RyldMPaH1k8IwQjT1KsQpn1Z-u_IAtnJL7_-u0tjyjOXRTHkiGaiCYSdqr68PuhQcX69ZiTrRXZEd6wzQWTMyyFOvzkVJJNdgSldh4Gtdd/s640/20191122_121858.jpg" width="640" height="480" data-original-width="1600" data-original-height="1200" /></a></div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQgRAqi4fexmveumJ5om0v7MUhJS4exHKTcQECk77cnZWRbXDCvuoCYJwCRbr1e6yjQiMzSeUQQxQ99TGY82KrH01YzvKFhh7vprL-YRuExT2_DwLbIUpsjK7xPD_Amt9_3AktDCj7Pmoy/s1600/20191122_121323.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQgRAqi4fexmveumJ5om0v7MUhJS4exHKTcQECk77cnZWRbXDCvuoCYJwCRbr1e6yjQiMzSeUQQxQ99TGY82KrH01YzvKFhh7vprL-YRuExT2_DwLbIUpsjK7xPD_Amt9_3AktDCj7Pmoy/s320/20191122_121323.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a>
<!--<h2>To catch up on</h2>
<ul>
<li></li>
<li></li>
</ul>-->
<h2>See Also</h2>
<ul>
<li><a href="https://www.salesforce.com/blog/2018/10/dreamforce-18-ultimate-content-guide.html">The Dreamforce 2018 Ultimate Content Guide</a></li>
</ul>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-70576764094066436142019-10-25T22:01:00.000+13:002019-10-25T22:44:26.366+13:00Dreamforce 2019 Session picks<p>Here are some of my current picks for Dreamforce 2019 sessions. I'm aiming for a mix of developer related topics in areas I want to learn more about plus anything that sounds informative. It isn't an exhaustive list and there are certainly some other session that I'll be adding.</p>
<h1>Most important session that I'm definitely going to attend</h1>
<p>I might be biased, but this session is on my must attend list. Yes, that's the <a href="http://www.fishofprey.com/2018/08/dreamforce-2018-session-picks.html">same thing I said last year</a>.</p>
<blockquote style="font-size: large;">This year Chris Peterson and I we will cover how taking up stripping can improve application security!</blockquote>
<table>
<tr>
<td style="width:33%">Think of combining the existing rigid security focus of the <a href="https://github.com/forcedotcom/force-dot-com-esapi">Salesforce Enterprise Security API (ESAPI)</a>.</td>
<td style="width:33%">With the flexibility of the new <code>Security.stripInaccessible()</a> method.</td>
<td style="width:33%">Into a hybrid that is both formally secure and stripped down on the CPU usage!</td>
</tr>
<tr>
<td style="background:white;text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZqC2SrX939UtcJ9uoL6QiHiI7-JG2Cl59BioQcHWTErE8m31WRv_fl-l_j5T3lPc3p-Dty_h8S9cPYiGSdZIDKctrDDYOG6tGUUUmc8VC3Ag2mv9ejGtNUZW1ygNRUOzFg5SvpaLVp3Hj/s1600/SecureCodey.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZqC2SrX939UtcJ9uoL6QiHiI7-JG2Cl59BioQcHWTErE8m31WRv_fl-l_j5T3lPc3p-Dty_h8S9cPYiGSdZIDKctrDDYOG6tGUUUmc8VC3Ag2mv9ejGtNUZW1ygNRUOzFg5SvpaLVp3Hj/s320/SecureCodey.png" width="148" height="320" data-original-width="180" data-original-height="388"
style="background:white;"/></a></td>
<td style="background:white;text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1iSoQV9giowcgr9CtxYZiRivN9acaX4vFuJ5gIDU6BQM0tNIWkI_6nbls7WWAZeOuIDrrjxaIRABF85mKoZQ9L8cvLalNtqfJXwniNPGqHmidLmmir0f9YN0e2JeU3g8extYyBXJ473om/s1600/CodeyDance.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1iSoQV9giowcgr9CtxYZiRivN9acaX4vFuJ5gIDU6BQM0tNIWkI_6nbls7WWAZeOuIDrrjxaIRABF85mKoZQ9L8cvLalNtqfJXwniNPGqHmidLmmir0f9YN0e2JeU3g8extYyBXJ473om/s320/CodeyDance.png" width="201" height="320" data-original-width="198" data-original-height="316" style="background:white;"/></a></td>
<td style="background:white;text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOsgbQ64-sVJmR7EKvgVhkLAaautU5tR6VaU8A_mJFeGP58lCyIVQ9yoQ5H2SIVo4fbS2r9RGzDeQzo3YYku9lS_ySFxouPaOqx_Uw0T4pbVIFv2Gp3AyA9zcpnLQIsUbo0_ZJBmXPg6Tz/s1600/CodeyMerged2.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOsgbQ64-sVJmR7EKvgVhkLAaautU5tR6VaU8A_mJFeGP58lCyIVQ9yoQ5H2SIVo4fbS2r9RGzDeQzo3YYku9lS_ySFxouPaOqx_Uw0T4pbVIFv2Gp3AyA9zcpnLQIsUbo0_ZJBmXPg6Tz/s320/CodeyMerged2.png" width="209" height="320" data-original-width="309" data-original-height="472" style="background:white;" /></a></td>
</tr>
</table>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1U#/session/a2q3A000002BJNlQAO">Reducing the cost of enforcing CRUD and FLS in the ESAPI</a>
<blockquote>Reworking the ESAPI to use the new pilot Apex feature to dramatically reduce the cost of checking FLS in Apex. Explore how the new Security.stripInaccessible (pilot) method can be utilized to enforce FLS during CRU[D] operations in the context of the existing ESAPI library.</blockquote>
</li>
</ul>
<h2>Keynotes</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1U#/session/a2q3A000002BJ9vQAG">Developer Keynote: Continuous Innovation with the Customer 360 Platform</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1U#/session/a2q3A000002BJ9zQAG">Platform Keynote: Digitally Transform with the Next-Gen Customer 360 Platform</a></li>
</ul>
<h2>Meet The *'s</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1UUAQ#/session/a2q3A000002BK1aQAG">True to the Core with Parker Harris and Bret Taylor</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1UUAQ#/session/a2q3A000002BGpsQAG">Meet the Developers</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1UUAQ#/session/a2q3A000002BGkVQAW">Panel Discussion: Meeting the ISV Product Team</a></li>
</ul>
<h2>Apex</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1U#/session/a2q3A000002BJXjQAO">Building self healing Apex apps through feature flags and Error Monitoring</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1U#/session/a2q3A000002BJNWQA4">Flow and Apex Showdown!</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1U#/session/a2q3A000002BJNiQAO">Make the Impossible Possible With Platform Cache!</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1U#/session/a2q3A000002BJNbQAO">Everything You Need to Know on Apex Debuggers</a></li>
</ul>
<h2>Customer 360</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1U#/session/a2q3A000002BKt9QAG">IT Visionaries: Using the Customer 360 Platform for Continuous Innovation</a> <a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1U#/session/a2q3A000002BKtAQAW">(2)</a></li>
</ul>
<h2>Salesforce DX</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1UUAQ#/session/a2q3A000002BJQBQA4">An Open Conversation about DX</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1U#/session/a2q3A000002BKp5QAG">Manage your Metadata with Package.xml and Salesforce CLI (1)</a></li>
<li><a href="https://success.salesforce.com/myagenda?eventId=a1Q3A000021ea1U#/session/a2q3A000002BJ2oQAG">Salesforce DX Technical Enablement Plugin</a></li>
<li><a href="https://success.salesforce.com/myagenda?eventId=a1Q3A000021ea1U#/session/a2q3A000002BJAuQAO">Leveraging Salesforce DX for Continuous Integration</a></li>
</ul>
<h2>APIs</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1U#/session/a2q3A000002BJx9QAG">Forbidden Secrets of the Metadata API</a></li>
</ul>
<!--h2>Peeking under the hood</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00000stRRuUAM#/session/a2q3A000001ytGEQAY">New Apex Compiler Rollout</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00000stRRuUAM#/session/a2q3A000001pwnDQAQ">How We Do the Magic We Do - A Peek into Multi-tenancy</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00000stRRuUAM#/session/a2q3A000001yuLjQAI">SOQL: Performance Explained</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00000stRRuUAM#/session/a2q3A000001ytGCQAY">How Salesforce does Incremental Code Deploys for internal orgs</a></li>
</ul-->
<h2>Platform Events</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1U#/session/a2q3A000002BJP8QAO">Microservices inside Salesforce with Platform Events and Change Data Capture</a></li>
</ul>
<h2>Platform</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1U#/session/a2q3A000002BGoIQAW">The Salesforce Customer 360 Platform Roadmap - Part I (1)</a> <a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1U#/session/a2q3A000002BJQIQA4">(2)</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1U#/session/a2q3A000002BJQHQA4">The Salesforce Customer 360 Platform Roadmap - Part II</a></li>
</ul>
<h2>Einstein / AI</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1U#/session/a2q3A000002BJMMQA4">An Introduction to Einstein Optical Character Recognition</a></li>
</ul>
<h2>ISV</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1U#/session/a2q3A000002BHBBQA4">ISV Basics: Security Reviews Explained</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1UUAQ#/session/a2q3A000002BJMTQA4">Introducing Managed Second-Generation Packages</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1UUAQ#/session/a2q3A000002BJQQQA4">Modern ALM: Release Management Patterns (1)</a> <a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1UUAQ#/session/a2q3A000002BJQXQA4">(2)</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1UUAQ#/session/a2q3A000002BJk9QAG">How storeConnect used 2GP and SFDX to Get to Market FAST!</a></li>
</ul>
<h2>Fun</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A000021ea1U#/session/a2q3A000002BJOnQAO">Developer Game Night</li>
</ul>
<h2>Lightning</h2>
<ul>
<li>TODO - Need something to fill out this area to be a well rounded developer. Lightning Roadmap maybe?</li>
<li></li>
</ul>
<!--René Winkelmeyer-->
<h2>See also</h2>
<ul>
<li>My <a href="http://www.fishofprey.com/2016/08/dreamforce-2016-session-picks-and.html#tips">General Dreamforce Tips</a> from a previous year</li>
<li>
Salesforce Engineering: <a href="https://engineering.salesforce.com/your-dreamforce-agenda-for-developers-118d7b6ad90">Your Dreamforce [2018] Agenda for Developers</a></li>
</ul>
FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-58701571412458485142019-06-24T21:26:00.000+12:002019-06-24T21:26:30.649+12:00FuseIT SFDC Explorer 3.12.19175.1 - Summer '19<p>Another roundup of some of the changes to the <a href="http://www.fuseit.com/explorer">FuseIT SFDC Explorer</a> since the <a href="http://www.fishofprey.com/2019/03/fuseit-sfdc-explorer-311190713-spring-19.html">3.11.19071.3</a> release.</p>
<h2>Fix for Salesforce breaking the Partner API</h2>
<p>One of the primary reasons to use the Partner API in an application is that it is org agnostic. It doesn't really care which org you are connecting to and will adjust to fit the shape of the org it is currently working with. So as long as you don't change the API version in the URL it will keep working indefinitely. Or at least, that is the theory...</p>
<p>Sadly, recent changes around the Real-Time Event Monitoring Beta <a href="https://salesforce.stackexchange.com/q/265096/102">caused metadata on a JSON field type to leak back into older Salesforce API versions</a>. See Known Issue: <a href="https://success.salesforce.com/issues_view?Id=a1p3A000001SHax">DescribeSObject call using the v45.0 Partner API are failing due to a complex type(json) that isn't defined in the WSDL</a>.</p>
<p>By updating to v46.0 of the Partner API we now avoid this issue. In older version it will manifest as a "There is an error in XML document" exception when making the describe call. </p>
<h2>View Executed Units from an Apex Log</h2>
<p>It's true, the Developer Console already has this information in a sub tab under the Execution Overview. Right now my version just shows the execution count for each Apex method and the basic execution time stats. It if isn't showing up, try turning on the timeline or parse tree first. The debug log will need to show the METHOD_ENTRY and METHOD_EXIT entries, so it the Apex Code logging level will need to be FINE or lower.</p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfrijWNHMrprOprvTHFub0G3EzsZxEsXGBQ1Y1IMXQyqkcer2r1AP2IwJmM0H4-8kx-79UkC_slKoyP-8Lztxl-V5Xafo-RSebsBvPOy9jdpDqGspXyCMs43Ed-H6J8t_9sWdZlGQuUpKZ/s1600/ExecutedUnits.PNG" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfrijWNHMrprOprvTHFub0G3EzsZxEsXGBQ1Y1IMXQyqkcer2r1AP2IwJmM0H4-8kx-79UkC_slKoyP-8Lztxl-V5Xafo-RSebsBvPOy9jdpDqGspXyCMs43Ed-H6J8t_9sWdZlGQuUpKZ/s1600/ExecutedUnits.PNG" data-original-width="870" data-original-height="432" width="760" /></a>
<h2 style="clear:both;">Wsdl2Apex : Make it easier to debug out stub objects</h2>
<p>Currently, if you try and debug out any of the proxy sObjects that get created for a SOAP callout you end up with a ton of extra *_type_info arrays. While necessary for <code>WebServiceCallout.invoke</code> they have zero usage in debugging the state of the request. They are generally constant and don't really reflect the useful state details.</p>
<p>I'd previously written about using JSON serialization to make repeating a SOAP callout easier. Then it occured to me, why not make all the _type_info arrays transient. Then they won't even appear in the debug output. That's exactly what I've done with the current WSDL2Apex build.</p>
<p>Sadly, transient doesn't work for <code>object.toString()</code>. I did raise an idea for it - <a href="https://success.salesforce.com/ideaView?id=0873A0000003euOQAQ">Provide a mechanism to exclude object variables/properties from toString()</a></p>
<!-- <li>Wsdl2Apex: Make all private *_type_info members transient to aid with JSON debug output.</li> -->
<h2>Reciprocal Logging Event selection and highlighting</h2>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhg0sjWIfcejVF3ELQb1aDPi8cA87sLYBHoAlQNFQpN8_mqAZPCw25gTaRMkahfsUpOJKuyLNvgYnKsT-9lJMWSgFcOFGqzVjlYfjL2cLz9yOKd_RlYJ0-_QJiFUMvr48UjAuoLgAGd1les/s1600/SelectPairedEvents.gif" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhg0sjWIfcejVF3ELQb1aDPi8cA87sLYBHoAlQNFQpN8_mqAZPCw25gTaRMkahfsUpOJKuyLNvgYnKsT-9lJMWSgFcOFGqzVjlYfjL2cLz9yOKd_RlYJ0-_QJiFUMvr48UjAuoLgAGd1les/s1600/SelectPairedEvents.gif" data-original-width="829" data-original-height="233" width="760" /></a>
<p>There are additional context menu options on a debug log to navigate between related opening and closing events. When applicable you can also select the parent event.</p>
<h2 style="clear:both;">Other changes 3.11</h2>
<ul>
<li>Update all API calls to use v46.0 Summer '19</li>
<li>Support for monitoring multiple test jobs.</li>
<li>ApexTestRunner: New async methods for checking test status. Beta throttled test runner.</li>
<li>Fix bug where the 10th column in SOQL results was always being blanked out. </li>
<li>Data Export CLI: Allow for parameters to vary in order.</li>
<li>Expanded support for deploying different Metadata types.</li>
<li>MetadataServiceWrapper - Support for .layout metadata types. Improve creation of package zips - only create the required folders.</li>
<li>Option to extract login credentials from a URL formed with "un" and "pw" query string parameters.</li>
<li>Wsdl2Apex: Handle SimpleType parameters. Warn if a Union simpleType is encountered.</li>
<li>Fix serverURL construction from sfdx cli logins.</li>
<li>Handle exceptions with SFDX logins</li>
</ul>
FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-67489701333953003832019-04-09T11:35:00.000+12:002019-08-22T07:27:27.138+12:00Trailhead: Deep Learning and Natural Language Processing<p>Recently I tackled the <a href="https://trailhead.salesforce.com/content/learn/modules/deep-learning-and-natural-language-processing">Deep Learning and Natural Language Processing</a> Trailhead module. </p>
<p>I can best summarize the experience with an image based on the <a href="https://www.reddit.com/r/ProgrammerHumor/comments/7r3hvl/if_the_authors_of_programming_textbooks_wrote/">Suppose you have one rabbit meme</a> explanation of arithmetic:</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSty9-sWqr3fpt5Vj6ONt7IHYOFzc_4H9iRSJDHZsRGlYhm9Kto9vBRUW425mLsoO4_iaIk2XGfiIKDfSla6hj09vtpea0yfxTUcQwbQmSp6Iu6wXs6HqZuiinAyQsvENqAp3mztekAc-4/s1600/Suppose+you+have+some+vectors.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSty9-sWqr3fpt5Vj6ONt7IHYOFzc_4H9iRSJDHZsRGlYhm9Kto9vBRUW425mLsoO4_iaIk2XGfiIKDfSla6hj09vtpea0yfxTUcQwbQmSp6Iu6wXs6HqZuiinAyQsvENqAp3mztekAc-4/s1600/Suppose+you+have+some+vectors.png" width="760" data-original-width="517" data-original-height="1600" /></a></div>
<p>To be fair, the first unit in the module does call out some prerequisites:</p>
<blockquote>This is an advanced topic, and this module assumes you have a basic understanding of machine learning vocabulary, some experience with Python, and at least a little hands-on experience working with machine learning data and algorithms. If you don’t already have that background, you can get yourself up to speed using the following resources.</blockquote>
<p>I personally think I meet those prerequisites. While I don't work with Python day to day the syntax is familiar enough I figured I can fake it till I make it.</p>
<p>The first two units were reasonably straight forward.</p>
<p>However, by the third unit - <a href="https://trailhead.salesforce.com/content/learn/modules/deep-learning-and-natural-language-processing/apply-dl">Apply Deep Learning to Natural Language Processing</a> it started to get complicated. In particular, with the <b>Hands-on Logistic regression</b> questions 6, and to a lesser extent question 7. These both required completing several TODO lines of Python to derive the loss after 100 epochs.</p>
<p>Let's look at the code from the first part of that that needed to be completed in the TODO sections:</p>
<script src="https://gist.github.com/FishOfPrey/43ae80b18f3595756ab042974107d321.js"></script>
<p>The challenge here is, as with all programming, that all the steps need to be completed successfully before you will get the expected answer. Get any of them wrong and things will go pear shaped fast. I could save you the pain of solving this challenge and provide you the full script, but that doesn't really go with the spirit on Trailhead. Instead I'll add some debugging outputs at various points to show the state of the tensors to hopefully make it clearer what should be happening. At least then if things start to go off track you can pick up the problem immediately.</p>
<h1>Exercise 6</h1>
<h2>TODO: Generate 2 clusters of 100 2d vectors, each one distributed normally, using only two calls of randn()</h2>
<pre>
println(classApoints)
tensor([[ 0.3374, -0.1778],
[-0.3035, -0.5880],
[ 0.3486, 0.6603],
[-0.2196, -0.3792],
#...
[-0.7952, -0.9178],
[ 0.4187, -1.1123],
[ 1.1227, 0.2646],
[-0.4698, 1.0866],
[-0.8892, 0.7647]])
assert(classApoints.size() == torch.Size([100, 2]))
</pre>
<pre>
println(classBpoints)
tensor([[ 0.4771, 0.7203],
[-0.0215, 1.0731],
[-0.1408, -0.5394],
[-1.2782, -0.8107],
#...
[ 1.1051, -0.5454],
[ 0.1073, 0.8727],
[-1.2800, -0.4619],
[ 1.4342, -1.2103],
[ 1.3834, 0.0324]])
assert(classBpoints.size() == torch.Size([100, 2]))
</pre>
<h2>TODO: Add the vector [1.0,3.0] to the first cluster and [3.0,1.0] to the second.</h2>
<pre>
println(classApoints)
tensor([[ 1.3374, 2.8222],
[ 0.6965, 2.4120],
[ 1.3486, 3.6603],
[ 0.7804, 2.6208],
#...
[ 0.2048, 2.0822],
[ 1.4187, 1.8877],
[ 2.1227, 3.2646],
[ 0.5302, 4.0866],
[ 0.1108, 3.7647]])
</pre>
<pre>
println(classBpoints)
tensor([[ 3.4771, 1.7203],
[ 2.9785, 2.0731],
[ 2.8592, 0.4606],
[ 1.7218, 0.1893],
#...
[ 4.1051, 0.4546],
[ 3.1073, 1.8727],
[ 1.7200, 0.5381],
[ 4.4342, -0.2103],
[ 4.3834, 1.0324]])
</pre>
<h2>TODO: Concatenate these two clusters along dimension 0 so that the points distributed around [1.0, 3.0] all come first</h2>
<pre>
println(inputs)
tensor([[ 1.3374, 2.8222],
[ 0.6965, 2.4120],
[ 1.3486, 3.6603],
[ 0.7804, 2.6208],
#...
[ 4.1051, 0.4546],
[ 3.1073, 1.8727],
[ 1.7200, 0.5381],
[ 4.4342, -0.2103],
[ 4.3834, 1.0324]])
println(inputs.size())
torch.Size([200, 2])
</pre>
<h2>TODO: Create a tensor of target values, 0 for points for the first cluster and # 1 for the points in the second cluster.</h2>
<pre>
println(classA)
tensor([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0])
println(classA.size())
torch.Size([100])
</pre>
<pre>
println(classB)
tensor([ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1])
println(classB.size())
torch.Size([100])
</pre>
<h2># TODO: Initialize a Linear layer to output scores for each class given the 2d examples</h2>
<pre>
println(model)
Linear(in_features=2, out_features=2, bias=True)
</pre>
<h2># TODO: Define your loss function</h2>
<p>Here you need to decide if you are going to use:</p>
<ol>
<li>MSE Loss for Regression</li>
<li>NLLLoss for Classification</li>
<li>CrossEntropyLoss for Classification</li>
</ol>
<p>Worst case here, you could just try them each one at a time until you get an answer that matches the expected answers in the Trailhead challenge.</p>
<h2>Finishing up exercise 6</h2>
<p>After that the rest should fall into place fairly easily based on the prior examples.</p>
<h1>Exercise 7: Logistic Regression with a Neural Network</h1>
<p>Firstly, the instructions when I completed this included this:</p>
<blockquote><pre># forward takes self and x as input
# passes x through linear_to_hidden, then a tanh activation function,
# and then <b>hidden_to_linear</b> and returns the output</pre></blockquote>
<p>I suspect that should actually be "and then <b>hidden_to_output</b> and returns the output".</p>
<p>The <a href="https://pytorch.org/docs/stable/torch.html?highlight=tanh#torch.tanh">torch.tanh</a> function is required for <code>forward</code>.</p>
<h2>Initialize your new network to have in_size 2, hidden_size 6, and out_size 2</h2>
<p>You are going to use the NeuralNet class that you just completed defining here.</p>
<h2>Define your loss function</h2>
<p>As with exercise 6, you can just try the 3 example loss functions to find a good fit for the expected answers.</p>
<h2>Finishing up exercise 7</h2>
<p>Most of the other parts for this question all fall into place based on the prior example.</p>
<h1>Results</h1>
<p>It would be accurate to say that this last unit took me way longer than the 90 minutes that Trailhead indicated. But dammit I earned those 100 measly points.</p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjWyWA_wC0kDKinFNAzg6UIVtZbB6glKsMs-0auTRQZXS7LuaKLFBH1ItIxYU8bTUgL5pbfSfZIzWnX4NQdnOFDgoG5-gmuJndj02xSA2AMFZAw0VrDoo69dwv5D8X6pVRBmvHQiEcHJ2s/s1600/100PointsB.PNG" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjWyWA_wC0kDKinFNAzg6UIVtZbB6glKsMs-0auTRQZXS7LuaKLFBH1ItIxYU8bTUgL5pbfSfZIzWnX4NQdnOFDgoG5-gmuJndj02xSA2AMFZAw0VrDoo69dwv5D8X6pVRBmvHQiEcHJ2s/s1600/100PointsB.PNG" data-original-width="346" data-original-height="344" /></a>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgae6phrfpvPz7BwB_O1pbxrg4goubop2v6venc0wf7i2DoAYTIL5GnBFkWOemHxMR3uKGHJhRXss4IHqLHoYbUD8YUZmpedrM3TjB9-f_z5QYzN_2lauE9_orwtupJXrmyOKhEHMnJJkSp/s1600/100Points.PNG" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgae6phrfpvPz7BwB_O1pbxrg4goubop2v6venc0wf7i2DoAYTIL5GnBFkWOemHxMR3uKGHJhRXss4IHqLHoYbUD8YUZmpedrM3TjB9-f_z5QYzN_2lauE9_orwtupJXrmyOKhEHMnJJkSp/s1600/100Points.PNG" data-original-width="650" data-original-height="616" /></a>
FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-68639168657780644122019-04-01T08:49:00.000+13:002019-04-01T08:49:56.143+13:00Trailhead Electric Imp plus plus<p>After completing the <a href="http://www.fishofprey.com/2018/03/the-trailhead-electric-imp-project.html">the Trailhead Electric Imp project</a> I was left wanting an excuse to access a number of other features of the imp001 hardware. Namely the accelerometer and pressure sensor. Yet there didn't seem many opportunities for a static fridge to fully utilize them.</p>
<p>While I was experimenting with this back in May 2018 the #BeABuilder challenge happened and I got sidetracked using the hardware for that instead. Somewhere in that process I never got around to hitting publish on this blog post, so here we are a year or so latter with a better late than never post.</p>
<p>Firstly I expanded the data model in Salesforce so I'd have fields to receive the additional data. This included the acceleration and pressure readings.</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Tinkering with a <a href="https://twitter.com/hashtag/Salesforce?src=hash&ref_src=twsrc%5Etfw">#Salesforce</a> Data Model for a current hobby project as part of the <a href="https://twitter.com/hashtag/BeABuilder?src=hash&ref_src=twsrc%5Etfw">#BeABuilder</a> challenge. Will be interesting to see if I can get it to work in practice. <a href="https://t.co/XRuGWwEDej">pic.twitter.com/XRuGWwEDej</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/991124792118935552?ref_src=twsrc%5Etfw">May 1, 2018</a></blockquote>
<p>Out of interest I tried getting the IoT Orchestration Traffic into a Lightning component. I didn't have much luck at the time and it didn't really liked to be iframed in.</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Day 4 of <a href="https://twitter.com/hashtag/BeABuilder?src=hash&ref_src=twsrc%5Etfw">#BeABuilder</a> challenge. The IoT Orchestration Traffic wasn't very cooperative with being iFramed into the page, so it needed some DOM based persuasion. <a href="https://t.co/4HAvojxsV8">pic.twitter.com/4HAvojxsV8</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/991511087060168705?ref_src=twsrc%5Etfw">May 2, 2018</a></blockquote>
<p>Hunting through the Salesforce Labs I found the <a href="https://t.co/iGHK2Zo8Fy">salesforce-iot-toolkit</a>. This provided some great visualizations via platform events as the data came in from the fridge. It directly monitored the platform events to drive the graphs. I found I needed to use the source based version rather than the app exchange version, which was missing a number of features.</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Day 8 of the <a href="https://twitter.com/hashtag/BeABuilder?src=hash&ref_src=twsrc%5Etfw">#BeABuilder</a> challenge. Using the Platform Event Stream Visualizer by <a href="https://twitter.com/DanHca?ref_src=twsrc%5Etfw">@DanHca</a> & <a href="https://twitter.com/MikeBrosseau?ref_src=twsrc%5Etfw">@MikeBrosseau</a>. App Exchange: <a href="https://t.co/O3OvgHNYqu">https://t.co/O3OvgHNYqu</a> Source: <a href="https://t.co/iGHK2Zo8Fy">https://t.co/iGHK2Zo8Fy</a> <a href="https://t.co/12Plq1lPoC">pic.twitter.com/12Plq1lPoC</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/993790165972799489?ref_src=twsrc%5Etfw">May 8, 2018</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Detect changes in fridge orientation. <a href="https://t.co/VFiwzPqxVr">pic.twitter.com/VFiwzPqxVr</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/994678644067876864?ref_src=twsrc%5Etfw">May 10, 2018</a></blockquote>
<!--<blockquote class="twitter-tweet" data-conversation="none" data-lang="en"><p lang="en" dir="ltr">Live fridge action <a href="https://t.co/3N2mJoO7rX">pic.twitter.com/3N2mJoO7rX</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/994683696555806720?ref_src=twsrc%5Etfw">May 10, 2018</a></blockquote>
-->
<h2>Dramatic reenactment of sensor usage</h2>
<iframe width="560" height="315" src="https://www.youtube.com/embed/DqfYm86dLwM" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<h2>Modified Agent Nut Source</h2>
<p>A few points of interest:</p>
<ol>
<li>My source was the version before they added proper refresh token support to handle expired sessions. So you probably don't want my version of <code>getStoredCredentials()</code></li>
<li>Added <code>#require</code> statements to access additional sensors.
<ul>
<li><a href="https://developer.electricimp.com/libraries/hardware/lps22hb">LPS22HB</a> - air pressure sensor</li>
<li><a href="https://developer.electricimp.com/libraries/hardware/lis3dh">LIS2DH12</a> - three-axis MEMS accelerometer</li>
<li><a href="https://developer.electricimp.com/libraries/hardware/ws2812">WS2812</a> - RGB LED</li>
</ul>
</li>
<li>Dropped the <code>READING_INTERVAL_SEC</code> down to 1 second to improve the accelerometer data.</li>
<li>Retrieved the X,Y, and Z axis acceleration values.</li>
<li>Retrieved the pressure sensor and additional temperature reading from that sensor as well.</li>
<li>Set the RGB color based on the current orientation indicated by the acceleration.</li>
<li>The LIS2DH12 sensor needed a non-default I<sup>2</sup>C address of <code>0x32</code>.</li>
</ol>
<script src="https://gist.github.com/FishOfPrey/46a21880092754d3ca7f5935eb2f017e.js"></script>
<h2>Modified Salesforce Platform Event Trigger Code</h2>
<p>Nothing fancy here. Just collect the additional properties the map them to the new custom fields.</p>
<pre name="code" class="Java">
trigger SmartFridgeReadingReceived on Smart_Fridge_Reading__e (after insert) {
List<SmartFridge__c> records = new List<SmartFridge__c>();
for (Smart_Fridge_Reading__e event : Trigger.New) {
SmartFridge__c record = new SmartFridge__c();
record.deviceId__c = event.deviceId__c;
record.temperature__c = event.temperature__c;
record.humidity__c = event.humidity__c;
record.door__c = event.door__c;
record.ts__c = event.ts__c;
record.accX__c = event.accX__c;
record.accY__c = event.accY__c;
record.accZ__c = event.accZ__c;
record.pressure__c = event.pressure__c;
record.temp2__c = event.temp2__c;
records.add(record); }
insert records;
}
</pre>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-41112793390192337232019-03-12T21:57:00.000+13:002019-03-12T21:57:50.042+13:00FuseIT SFDC Explorer 3.11.19071.3 - Spring '19<p>Another roundup of some of the changes to the <a href="http://www.fuseit.com/explorer">FuseIT SFDC Explorer</a> since the <a href="http://www.fishofprey.com/2018/07/fuseit-sfdc-explorer-39181901-summer-18.html">3.9.18190.1</a> release.</p>
<h2>Bypass sObject types based of suffix to speed up metadata retrieval</h2>
<p>With the update to v45.0 of the APIs there is now describe metadata coming back for change data capture with the suffix <code>__ChangeEvent</code>. This can be useful, <i>except</i> every custom object also gets a change event. If you have a large number of custom objects it can quickly become overwhelming. </p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxsVgg-yRoFBXsC28mM_1yPxIGBufsbi_PU7OI8z8R7-ssjZeA2-QkuOYsQKjbHQ6JjYOoub5oaLyi0Lvsc9Mbz6TPwKwOaa46e5PVFiL2euIF9ga8h-3jcE-DtgCu-GEtKO8QM0q4M0Sh/s1600/sObjectTypeFiltering.PNG" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxsVgg-yRoFBXsC28mM_1yPxIGBufsbi_PU7OI8z8R7-ssjZeA2-QkuOYsQKjbHQ6JjYOoub5oaLyi0Lvsc9Mbz6TPwKwOaa46e5PVFiL2euIF9ga8h-3jcE-DtgCu-GEtKO8QM0q4M0Sh/s1600/sObjectTypeFiltering.PNG" data-original-width="554" data-original-height="237" /></a>
<p>I've added a filter option to the sObject metadata browser that defaults to only showing __c, __mdt, and __e. Other options can be turned on if you want to see them. A refresh is required for the changes to take affect.</p>
<h2>Expanded Asynchronous Test Results view</h2>
<p>After the async tests have finished running you will set the total duration by Apex class and method. This can be useful for identifying which test methods contribute the most to the overall test run time.</p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9yQzc3bbuIjW8Vb5xqbXiWeN3PqiXCbo6Qq5cB5xvD7A8w5z27fdLjT4utF2sljYXc63Tskvyo0nM4mj4cmf8rwu8l0eOsMU3Cu2trSU-vy0is5sbZ4yxCUdLQk56QflLgbGaErIRb8zy/s1600/TestRunDuration.PNG" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9yQzc3bbuIjW8Vb5xqbXiWeN3PqiXCbo6Qq5cB5xvD7A8w5z27fdLjT4utF2sljYXc63Tskvyo0nM4mj4cmf8rwu8l0eOsMU3Cu2trSU-vy0is5sbZ4yxCUdLQk56QflLgbGaErIRb8zy/s1600/TestRunDuration.PNG" data-original-width="567" data-original-height="201" /></a>
<h2>Expose the logging levels in the menu</h2>
<p>You can alter the current logging levels for the current DebugLevel and then use "Update Current TraceFlag" to apply them to Salesforce.</p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieoJ5srmKOtsnqTSHRKdb6qF3m-tKQV94uHRVyquXUdk8yNkfvJkTPo7r0Q1cR0ni-JgtgzuF8DZ9xKKsROt3jIB1k002rlnuqth0JoXmJl48jiYSAkLvm8Ox0jsxGqJb1TNuXtx-HaNsP/s1600/LoggingLevels.PNG" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieoJ5srmKOtsnqTSHRKdb6qF3m-tKQV94uHRVyquXUdk8yNkfvJkTPo7r0Q1cR0ni-JgtgzuF8DZ9xKKsROt3jIB1k002rlnuqth0JoXmJl48jiYSAkLvm8Ox0jsxGqJb1TNuXtx-HaNsP/s1600/LoggingLevels.PNG" data-original-width="334" data-original-height="299" /></a>
<p>The "Disable Logging" menu option will remove the current TraceFlag, which will stop further logging from occurring.</p>
<h2>Wsdl2Apex</h2>
<p>There have been a number of changes to the Wsdl2Apex processing to support more edge cases:</p>
<ol>
<li>Allow for schema imports via schema imports (nested imports). Includes checks for circular references.</li>
<li>If the complex type can't be found in the current schema search the imported schema for it.</li>
<li>If a SimpleType has a restriction that isn't primitive then search the underlying types for the primitive type that can be converted to Apex.</li>
<li>Detect repeated imported schema target namespaces</li>
<li>Use common code to create Apex class names from complex types.</li>
<li>Add generated Apex comments to classes that extend a base type.</li>
<li>Attempt to compile the XmlSchema to resolve groups so they can be automatically expanded.</li>
<li>Include warning messages on web methods where the return type can't be resolved from the namespace.</li>
</ol>
<h2>Include Apex class name in code coverage breakdown</h2>
<p>The Apex class name and test method name will be included with the class coverage breakdown details.</p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgANCU7PdkdbhJUDajZ0RBgefLLda4kUXNq9idjqiTj15xK6Q43Ko3wd3T84TXLm8hlg-pOE-P7EA1JxBi8iExiI7h4_tbiw3HxKM7tCnt9thWRAez4mxx6UEGzFTcRohHv7XN3ADJWMHFF/s1600/CoverageClassNames.PNG" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgANCU7PdkdbhJUDajZ0RBgefLLda4kUXNq9idjqiTj15xK6Q43Ko3wd3T84TXLm8hlg-pOE-P7EA1JxBi8iExiI7h4_tbiw3HxKM7tCnt9thWRAez4mxx6UEGzFTcRohHv7XN3ADJWMHFF/s1600/CoverageClassNames.PNG" data-original-width="643" data-original-height="212" /></a>
<h2>JWT Authentication for Salesforce sessions</h2>
<p>It is now possible to use the <a href="https://help.salesforce.com/articleView?id=remoteaccess_oauth_jwt_flow.htm&type=5">OAuth 2.0 JWT Bearer Token flow</a> to authenticate with Salesforce. I'll expand on the steps to do this shortly, which will include configuring the connected app and registering the X509 Certificate.</p>
<h2 style="clear:both;">Other changes 3.11</h2>
<ul>
<li>Middle click to hide tab. Improve tab hiding.</li>
<li>Improve support for using the ToolingAPI in the EntityViewer.</li>
<li>If directly updating a nullable int in the SOQL results treat it as such (rather than a string)</li>
<li>Format a VF_PAGE_MESSAGE in the log timeline</li>
<li>Format display of ApexResult and HeapDump from the Tooling API SOQL Queries.</li>
<li>Allow for a CultureInfo.DateTimeFormat.TimeSeparator other than ":". Force the SOQL building code to use the InvarientCulture so the required format is applied.</li>
<li>Update core SalesforceSession to use v45.0 (Spring 19) APIs</li>
<li>For the Apex Log Stack, include the Soql Execute Count</li>
<li>Option to run the most recent async test cases again after a successful metadata deployment.</li>
<li>EntityViewer - Allow for ToolingAPI entities.</li>
<li>Event Log Viewer. Only show the first 4000 rows of data.</li>
<li>Log Timeline control. Show icons for Test.startTest() and Test.stopTest() if they are detected.</li>
<li>Handle failure to query for recent apex test runs.</li>
<li>When generating anonymous Apex to get the current Session ID include the SalesforceBaseUrl</li>
<li>Code Generation - If generating without custom fields, exclude picklist values containing "__". These typically represent relationships to custom sObjects<br/>
Detect and skip duplicate picklist value entries.<br/>
Fix the generated properties for *Picklist to set based on the enum value rather than the description attribute.<br/>
Detect references to sObjects that aren't exposed via the metadata.</li>
<li>Regenerate sObjects (plus associated services and data sources) for API v44.0.</li>
<li>CodeGeneration - If configured, exclude relationships to custom fields.</li>
Don't generate types for __ChangeEvent, __History, __Share
<li>CodeGeneration - generate "extends" for Apex classes extending other classes.</li>
Expand details for WebServiceCallout.invoke with comments.
<li>ApexClass (for generation) - Track if the Apex classes extends a base class.</li>
<li>FieldService - When extracting child elements from a query result skip nodes that aren't XmlElements.</li>
<li>ToolingServiceWrapper - Add describeGlobalCached() that caches describeGlobal() to improve performance.</li>
<li>SalesforceSession - If an exception occurs with a WebRequest include the complete URL in the Exception.Data</li>
<li>Internal caching of the Tooling API DescribeGlobalResult Metadata</li>
<li>Auto-size columns in SOSL & single page SOQL results</li>
<li>Improve usage of direct Csv loading. Support bulk load for larger operations. Allow the primary sObject type to be defined.</li>
<li>Change the Apex log layout with the treeview between horizontal and vertical.</li>
<li>Define logging levels via common menu, Handle hitting the maximum debug log count</li>
<li>Capture SSL/TLS config issues and provide help link to dedicated help page.</li>
<li>When checking metadata deployment successes, highlight changed components vs. unchanged.</li>
</ul>FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-21608575637214622572018-10-03T22:40:00.000+13:002018-10-05T07:39:59.932+13:00Dreamforce 2018 Roundup / Summary<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtjMdfyKw8XSvFcTanJx-RJKg_E_CQKH5iYogkzU0C98wG8I9xnfDTq2RYqEyKJA8Pk3mtZrm6eKudYdu4TjyHdTVljt1JLk9J9hBp4Bsijzv0FdiFwcSFIVibRYemZ0uvQk9Y8cl_lF3f/s1600/20180925_151729.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtjMdfyKw8XSvFcTanJx-RJKg_E_CQKH5iYogkzU0C98wG8I9xnfDTq2RYqEyKJA8Pk3mtZrm6eKudYdu4TjyHdTVljt1JLk9J9hBp4Bsijzv0FdiFwcSFIVibRYemZ0uvQk9Y8cl_lF3f/s800/20180925_151729.jpg" width="750" data-original-width="1600" data-original-height="900" /></a></div>
<a href="https://github.com/afawcett/df18-dx-demo"></a>
<p>The recap for this Dreamforce is going to come across as a bit of a photo journal as I go back through my phones timeline to piece back together what I got up to. Somehow, even on my 5th time attending this conference things still went past at a frantic pace.</p>
<!--div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjw6Wnn7y6Y891OlUuQjf9ppwVMIqVOXksTTXPfP2qtUNU76ou7B_bU7vLwJDOOVVj_d_JkY_jdA7BE81yajCIVCdOt_z2qAcFMQfqGnhVNhrW7VNllAN-P3ZbsbpEITAT1f-RMM4YlXUJI/s1600/20180925_151651.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjw6Wnn7y6Y891OlUuQjf9ppwVMIqVOXksTTXPfP2qtUNU76ou7B_bU7vLwJDOOVVj_d_JkY_jdA7BE81yajCIVCdOt_z2qAcFMQfqGnhVNhrW7VNllAN-P3ZbsbpEITAT1f-RMM4YlXUJI/s800/20180925_151651.jpg" width="750" data-original-width="1600" data-original-height="900" /></a></div-->
<h2 style="clear: both;">Table of Contents</h2>
<ol>
<li><a href="#preconference">Preconference</a></li>
<li><a href="#day1">Day One</a>
<ul>
<li>My Presentation</li>
<li>Main Keynote</li>
</ul>
</li>
<li><a href="#day2">Day Two</a>
<ul>
<li>The Lightning Platform Roadmap</li>
<li>Dreamfest</li>
</ul>
</li>
<li><a href="#day3">Day Three</a>
<ul>
<li>Developer Keynote</li>
<li>Meet the Developers</li>
<li>True to the Core</li>
</ul>
</li>
<li><a href="#day4">Day Four</a>
<ul>
<li>Mulesoft</li>
</ul>
</li>
<li><a href="#deploymentFish">Deployment Fish</a></li>
</ol>
<hr/>
<h2 style="clear: both;" id="preconference">Preconference</h2>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKRL4Jfq6_JganXit0yF7R4iobuXSWzvI8Zp5kWEWdoh8jVCdL8PkmaSyml8SOrHKbkUKXNobIqcgltqDs6dPM96VzgM4a-YF8T7LeZjKlzOnsXWA0CyyGTp4qkxHAl13I5cDrs6jL_V3d/s1600/20180924_155221.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKRL4Jfq6_JganXit0yF7R4iobuXSWzvI8Zp5kWEWdoh8jVCdL8PkmaSyml8SOrHKbkUKXNobIqcgltqDs6dPM96VzgM4a-YF8T7LeZjKlzOnsXWA0CyyGTp4qkxHAl13I5cDrs6jL_V3d/s320/20180924_155221.jpg" width="180" height="320" data-original-width="900" data-original-height="1600" /></a></div>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-uDNXXbpKCixznpp2d3u6jFMYlUl9mCR5DjwxXyOHq6dtRueTNxzBPbonwmXEg36er0z9WliB1X5YNq7DYz5VnZDJHNX0xJcU4I9VN7cTxmL7Jt06iWeQZqP1avQSiBiy81KX7oEwx8gV/s1600/20180924_184545.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-uDNXXbpKCixznpp2d3u6jFMYlUl9mCR5DjwxXyOHq6dtRueTNxzBPbonwmXEg36er0z9WliB1X5YNq7DYz5VnZDJHNX0xJcU4I9VN7cTxmL7Jt06iWeQZqP1avQSiBiy81KX7oEwx8gV/s320/20180924_184545.jpg" width="180" height="320" data-original-width="900" data-original-height="1600" /></a></div>
<p>A visit to the Salesforce Tower for the Tooling Partner meeting. Then a quick visit to the Salesforce Park (<a href="https://sf.curbed.com/2018/9/25/17903758/transbay-transit-center-closed-salesforce-park">the day before it was closed due to structural damage</a>).</p>
<h2 id="day1" style="clear: both;">Day One</h2>
<h3><a href="https://success.salesforce.com/0693A000006jVIT">Testing Lightning Flow Automations</a></h3>
<ul>
<li>Usage of <code>Test.loadData()</code> to prep records for testing from a static resource.</li>
<li>Starting auto launched flows from a testing context.</li>
<li>In Winter'19 - Use the <code>FlowTestCoverage</code> and <code>FlowElementTestCoverage</code> from the Tooling API to get coverage details for flows. See <a href="https://releasenotes.docs.salesforce.com/en-us/winter19/release-notes/rn_forcecom_flow_test_coverage.htm">Track Process and Flow Test Coverage</a></li>
</ul>
<h3><a href="https://success.salesforce.com/myagenda?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WUY5QAO">DX Super Session</a> <a href="https://www.youtube.com/watch?v=AkkyKBfLQr8">(Video)</a></h3>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">New scratch org snapshots. In pre-release it is using the 0TT key prefix. Which is a Trailforce Template.<a href="https://twitter.com/hashtag/DF18?src=hash&ref_src=twsrc%5Etfw">#DF18</a> <a href="https://t.co/d7EqiEO3yA">pic.twitter.com/d7EqiEO3yA</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1044644000316026880?ref_src=twsrc%5Etfw">September 25, 2018</a></blockquote>
<p>New scratch org "snapshots" to use as the starting point for creating additional scratch orgs. The snapshot can be used to pre-configure the scratch org in a known state. E.g. with the dependent packages installed and test data loaded. They are currently using the <a href="http://www.fishofprey.com/2011/09/obscure-salesforce-object-key-prefixes.html#0TT">0TT Trailforce Template</a> keyprefix. Note that any orgPreferences are additive over what is already present in the snapshot.</p>
<!--Snapshots for scratch orgs. Create a scratch org in a known initial shape. E.g. Sample data pre-loaded. Package dependencies already installed and configured.-->
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaQTA3hLTicxxGGI54YZ1_expW4EMjokFrGghHA3SK7ZAIt0Je0S_GWUZziaDDDncA1aeVTcsQERBckjR-urhSOnuRZCvsNFI81Uz0u3JCEp-O6sXkXN9LGU2of08FGsNja4BEbuNRaRLK/s1600/20180925_103803.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaQTA3hLTicxxGGI54YZ1_expW4EMjokFrGghHA3SK7ZAIt0Je0S_GWUZziaDDDncA1aeVTcsQERBckjR-urhSOnuRZCvsNFI81Uz0u3JCEp-O6sXkXN9LGU2of08FGsNja4BEbuNRaRLK/s320/20180925_103803.jpg" width="320" height="180" data-original-width="1600" data-original-height="900" alt="spinners" /></a></div>
<p>FORCE_SHOW_SPINNER and FORCE_SPINNER_DELAY <a href="https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_cli_env_variables.htm">environment options</a> that can make automating the CLI easier. They prevent the spinner coming back on the standard output.</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2rhOvy6MYl7ikC8ptBifRKz6Aax42cvOR77BEPdKqvh00M5edTMfk_Lgw_t0I5TzP8GOxUuQuSm_6R55VyCzfa6bm9A4fXN7MFOPADcbZis4eh_kvoyf9fSNzlN1BHoN9-f6FcPHrPMFM/s1600/20180925_110422.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2rhOvy6MYl7ikC8ptBifRKz6Aax42cvOR77BEPdKqvh00M5edTMfk_Lgw_t0I5TzP8GOxUuQuSm_6R55VyCzfa6bm9A4fXN7MFOPADcbZis4eh_kvoyf9fSNzlN1BHoN9-f6FcPHrPMFM/s320/20180925_110422.jpg" width="320" height="180" data-original-width="1600" data-original-height="900" /></a></div>
<p><a href="https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_force_package.htm#cli_reference_create">Naming</a> for unlocked package versions.</p>
<ul style="clear: both;">
<li>Source for the demo - <a href="https://github.com/afawcett/df18-dx-demo">https://github.com/afawcett/df18-dx-demo</a></li>
</ul>
<h3 style="clear: both;">My Presentation</h3>
<p>I've done a whole separate blog post to cover my talk - <a href="http://www.fishofprey.com/2018/09/happysoupmix.html">Dreamforce 2018 Presentation - Understand your Org shape via visualization of Metadata Component Dependencies</a>.</p>
<h3>Main keynote</h3>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">It’s Keynote time! <a href="https://twitter.com/hashtag/DF18?src=hash&ref_src=twsrc%5Etfw">#DF18</a> <a href="https://twitter.com/hashtag/MVP?src=hash&ref_src=twsrc%5Etfw">#MVP</a> Thanks <a href="https://twitter.com/hollygfirestone?ref_src=twsrc%5Etfw">@hollygfirestone</a> <a href="https://twitter.com/lexpisani?ref_src=twsrc%5Etfw">@lexpisani</a> & team for herding us into our seats 😍 <a href="https://t.co/Onh6W3bDIF">pic.twitter.com/Onh6W3bDIF</a></p>— Kristi Campbell Guzman (@KristiForce) <a href="https://twitter.com/KristiForce/status/1044703378637385729?ref_src=twsrc%5Etfw">September 25, 2018</a></blockquote>
<p>Demo's of Einstein voice to convert speech, to text, to actions within Salesforce.</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Einstein Voice is FREE!!!! Control Salesforce using your voice!!</p>— David K. Liu (@dvdkliu) <a href="https://twitter.com/dvdkliu/status/1044727090224877568?ref_src=twsrc%5Etfw">September 25, 2018</a></blockquote>
<div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/MK_mrT7Kmw9ygMrhhLWO-rM-h-vRsTiKmi2t5-f-1-hybZ_42ZOF5wCpDOqm1kYJ84EByYyOYNtvZ35lIfse7w6P2OhZLX6949Nz1m2maBhwtSX1EkWaBSzypTzKkfLfoMFT123c" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://1.bp.blogspot.com/MK_mrT7Kmw9ygMrhhLWO-rM-h-vRsTiKmi2t5-f-1-hybZ_42ZOF5wCpDOqm1kYJ84EByYyOYNtvZ35lIfse7w6P2OhZLX6949Nz1m2maBhwtSX1EkWaBSzypTzKkfLfoMFT123c" width="320" height="218" data-original-width="666" data-original-height="454" /></a></div>
<p>Customer 360 - Create a canonical view of the customer across Marketing Cloud, Commerce Cloud, and Service Cloud.</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Oh. I need one of those for a current project. Where can I get a <a href="https://twitter.com/hashtag/df18?src=hash&ref_src=twsrc%5Etfw">#df18</a> Customer 360 balloon. <a href="https://t.co/B56R3GCu9r">pic.twitter.com/B56R3GCu9r</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1044722909086867457?ref_src=twsrc%5Etfw">September 25, 2018</a></blockquote>
<h3>MVP Party</h3>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvxFJq8Y8GliM38iNsK9SlpfM54L-ZEhMU3cV9mjhEmC2JwZzopfL7zpYRz98rpN7ylnRYSCHjZMb-cyU8XnGiskv7mwXsQemVSxhtau26b2fqw-niz2EcX75fLw5xjrl7UCKYjNl2vxsK/s1600/20180925_201212.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvxFJq8Y8GliM38iNsK9SlpfM54L-ZEhMU3cV9mjhEmC2JwZzopfL7zpYRz98rpN7ylnRYSCHjZMb-cyU8XnGiskv7mwXsQemVSxhtau26b2fqw-niz2EcX75fLw5xjrl7UCKYjNl2vxsK/s800/20180925_201212.jpg" width="750" data-original-width="1600" data-original-height="764" /></a></div>
<p>This year it was at the Tonga Room & Hurricane Bar. The band on the boat was 👌.</p>
<h2 id="day2">Day Two</h2>
<h3>The Lightning Platform Roadmap - <a href="https://success.salesforce.com/myagenda?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WUYBQA4">Part I</a> and <a href="https://success.salesforce.com/myagenda?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WUYCQA4">Part II</a></h3>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Changes coming to Apex from the roadmap <a href="https://twitter.com/hashtag/DF18?src=hash&ref_src=twsrc%5Etfw">#DF18</a> session. Yay for FLS/CRUD enforcement getting better native support. <a href="https://t.co/Eyp6VVwXqH">pic.twitter.com/Eyp6VVwXqH</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1044978778684841984?ref_src=twsrc%5Etfw">September 26, 2018</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Support for non scratch org dev from the CLI. Plus pre and post command hooks. <a href="https://twitter.com/hashtag/DF18?src=hash&ref_src=twsrc%5Etfw">#DF18</a> <a href="https://t.co/TflpFCzmKU">pic.twitter.com/TflpFCzmKU</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1044979203920166912?ref_src=twsrc%5Etfw">September 26, 2018</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Apex extract method and other refactoring support. Preview of an entirely web based IDE. <a href="https://twitter.com/hashtag/DF18?src=hash&ref_src=twsrc%5Etfw">#DF18</a> <a href="https://t.co/4rgQrDOVMF">pic.twitter.com/4rgQrDOVMF</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1044979555130257408?ref_src=twsrc%5Etfw">September 26, 2018</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Sandbox cloning. Targeting both a sandbox and scratch of to a specific release version. <a href="https://twitter.com/hashtag/DF18?src=hash&ref_src=twsrc%5Etfw">#DF18</a> <a href="https://t.co/B35dMvA12e">pic.twitter.com/B35dMvA12e</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1044979906717732869?ref_src=twsrc%5Etfw">September 26, 2018</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">The ability to create a snapshot of a Scratch org to use as a template for creating new scratch org. Useful to get all the pre setup and data load done.</p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1044980428640145408?ref_src=twsrc%5Etfw">September 26, 2018</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">2nd generation packages for managed packages, along with a migration path. <a href="https://twitter.com/hashtag/DF18?src=hash&ref_src=twsrc%5Etfw">#DF18</a> <a href="https://t.co/fnVUNFzOFK">pic.twitter.com/fnVUNFzOFK</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1044980814713249793?ref_src=twsrc%5Etfw">September 26, 2018</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Integration roadmap via <a href="https://twitter.com/extraidea?ref_src=twsrc%5Etfw">@extraidea</a> at <a href="https://twitter.com/hashtag/DF18?src=hash&ref_src=twsrc%5Etfw">#DF18</a> <a href="https://t.co/K3cCTDi4iq">pic.twitter.com/K3cCTDi4iq</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1044991921561583616?ref_src=twsrc%5Etfw">September 26, 2018</a></blockquote>
<h2 style="clear: both;" id="day3">Day Three</h2>
<h3><a href="https://youtu.be/C6Cp2P5Eb7Y">Developer Keynote</a></h3>
<p>Lightning Developer Pro Sandboxes - Spin up faster than a traditional Sandbox. Approx 5 minutes to activate (versus a few hours to even days).</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdqx7zdZ4i3fG6LAbAb0K2NFJ6uilYzEKwT9vUfG1Oh42XrPfh7HQa3Ep1rLGckTmSo5Ofi32BiBEJExMm-m7ps8yC05uQ6XFmfvfAA3vgHp_YdNxjG8GaIRioS5zb-ouaFzqtEifHcDXG/s1600/20180927_134951.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdqx7zdZ4i3fG6LAbAb0K2NFJ6uilYzEKwT9vUfG1Oh42XrPfh7HQa3Ep1rLGckTmSo5Ofi32BiBEJExMm-m7ps8yC05uQ6XFmfvfAA3vgHp_YdNxjG8GaIRioS5zb-ouaFzqtEifHcDXG/s640/20180927_134951.jpg" width="640" height="251" data-original-width="1600" data-original-height="628" /></a></div>
<p>Another example of a named package version.</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Using <a href="https://twitter.com/MuleSoft?ref_src=twsrc%5Etfw">@MuleSoft</a> anypoint to aggregate multiple APIs into a single endpoint at the <a href="https://twitter.com/hashtag/DF18?src=hash&ref_src=twsrc%5Etfw">#DF18</a> dev keynote. <a href="https://t.co/ems78qtGXS">pic.twitter.com/ems78qtGXS</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1045411745420926976?ref_src=twsrc%5Etfw">September 27, 2018</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Spring 19 roadmap from the <a href="https://twitter.com/SalesforceDevs?ref_src=twsrc%5Etfw">@SalesforceDevs</a> <a href="https://twitter.com/hashtag/DF18?src=hash&ref_src=twsrc%5Etfw">#DF18</a> keynote <a href="https://t.co/KVGoIP8nqN">pic.twitter.com/KVGoIP8nqN</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1045416474335006720?ref_src=twsrc%5Etfw">September 27, 2018</a></blockquote>
<!--h3>Development Roadmap for Spring '19</h3>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCMEt3B3KKdiJbIOfhEfEZTJjLeVeucjK9UTzbPhCceUa6ksZmxhK-ToFgL0qTid1Ci3F6UlqSQuI83PBSHlMj28UUp7MS5iKifQiUWfO3jC31T5aSVqKS5gN0DVWmG1s4JaqX4JRnwp-q/s1600/20180927_135305.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCMEt3B3KKdiJbIOfhEfEZTJjLeVeucjK9UTzbPhCceUa6ksZmxhK-ToFgL0qTid1Ci3F6UlqSQuI83PBSHlMj28UUp7MS5iKifQiUWfO3jC31T5aSVqKS5gN0DVWmG1s4JaqX4JRnwp-q/s640/20180927_135305.jpg" width="640" height="348" data-original-width="1600" data-original-height="871" /></a></div-->
<h3>True to the Core</h3>
<p>Lots of coverage of how Salesforce will work towards reinvigorating the idea exchange to handle the current scale. In particular, limiting each users ability to vote of every possible idea. Forcing them to focus on what is most important to them. Salesforce will then commit to working on the highest rated ideas.</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">So everyone who saw True to the Core at <a href="https://twitter.com/Dreamforce?ref_src=twsrc%5Etfw">@Dreamforce</a> today, what do you think of our IdeaExchange plan? Send me feedback! CC <a href="https://twitter.com/parkerharris?ref_src=twsrc%5Etfw">@parkerharris</a> <a href="https://twitter.com/jennyst0?ref_src=twsrc%5Etfw">@jennyst0</a> <a href="https://twitter.com/mike945778?ref_src=twsrc%5Etfw">@mike945778</a></p>— Bret Taylor (@btaylor) <a href="https://twitter.com/btaylor/status/1045128979886133249?ref_src=twsrc%5Etfw">September 27, 2018</a></blockquote>
<h3>Everything that's Awesome with Apex</h3>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcfiZvHLjhqwm0HaZUVPuQOEO0wftPi7cBjaUAviagytxtEWrxwUfLZrk4z_LPW8CWWJlNT_ClOmiFlYW9CuUw71OPqjtaalQqPh623ITqf6qD0if2uQiIzLcVwduWFoprIdEdjzgmDtk4/s1600/slide_14.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcfiZvHLjhqwm0HaZUVPuQOEO0wftPi7cBjaUAviagytxtEWrxwUfLZrk4z_LPW8CWWJlNT_ClOmiFlYW9CuUw71OPqjtaalQqPh623ITqf6qD0if2uQiIzLcVwduWFoprIdEdjzgmDtk4/s320/slide_14.jpg" width="320" height="180" data-original-width="1024" data-original-height="577" /></a></div>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6Id_2_h9rK82U1q-Nz_cwuYJLVRFj8u_5R_q8Np-Ie8yQTnGPb5Yh728Ce__i25ie05749R8n0JD8ehpV4TO0s-mwP2fZ-naGGWkfWGMP_UmziYKH19TR4MOdpC9cjWiZOAquHXuQuMWG/s1600/slide_15.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6Id_2_h9rK82U1q-Nz_cwuYJLVRFj8u_5R_q8Np-Ie8yQTnGPb5Yh728Ce__i25ie05749R8n0JD8ehpV4TO0s-mwP2fZ-naGGWkfWGMP_UmziYKH19TR4MOdpC9cjWiZOAquHXuQuMWG/s320/slide_15.jpg" width="320" height="180" data-original-width="1024" data-original-height="577" /></a></div>
<p>(<a href="https://speakerdeck.com/ca_peterson/df18-everything-thats-awesome-with-apex">Slides</a>)</p>
<p>Roadmap for Spring '19 and Summer '19</p>
<ul>
<li>Exposing the Org Limit details in Apex. E.g. Daily Asysnc Apex executions.</li>
<li>Support for creating Scratch Orgs with access to Platform Cache.</li>
<li>Support for "rename symbol" refactoring in Apex via the Apex Language Services, and by extension Visual Studio Code. Longer term, this may expand to implementing interfaces and extracting variables.</li>
<li style="clear: both;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaM-3zHY05-3avns4zCtccl4NWFTw20BzTAnWH-CLxO3Y8YhnWfjW9WQZBojTWRYglK5tw6-HDl7zrYxwzI3ZVYNdHXPsVgw3kkQOMZb2IY96ufCbTlok6XIJxGIym1hyYyGKu7VesbfGs/s1600/slide_20.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaM-3zHY05-3avns4zCtccl4NWFTw20BzTAnWH-CLxO3Y8YhnWfjW9WQZBojTWRYglK5tw6-HDl7zrYxwzI3ZVYNdHXPsVgw3kkQOMZb2IY96ufCbTlok6XIJxGIym1hyYyGKu7VesbfGs/s320/slide_20.jpg" width="320" height="180" data-original-width="1024" data-original-height="577" /></a></div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-0gak4bWAL1hUUJ5PYVpzrdw8fAce1DWw8cQa_CjbHffO4AYf3FU-1FagZqSozqfbP-VAMQifMzoxpGSw0oev0w9CnM9yNh0g67R9pLJCruEmaO9wcf1lAOBsRHt-VohvqnI5VWeKFLxq/s1600/slide_21.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-0gak4bWAL1hUUJ5PYVpzrdw8fAce1DWw8cQa_CjbHffO4AYf3FU-1FagZqSozqfbP-VAMQifMzoxpGSw0oev0w9CnM9yNh0g67R9pLJCruEmaO9wcf1lAOBsRHt-VohvqnI5VWeKFLxq/s320/slide_21.jpg" width="320" height="180" data-original-width="1024" data-original-height="577" /></a></div>Improved support for enforcing Field Level Security (FLS) and Create,Read,Update,Delete (CRUD) in Apex. Goal is to reduce the amount of processing that was historically required to do this. It's particularly important for those publishing on the App Exchange.
https://twitter.com/FishOfPrey/status/1044978778684841984</li>
</ul>
<h3 style="clear: both;">Quip Party</h3>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7CE81mmHPbRR4L5Suyh2Tnwf7tqQ4vquF22rEzZUISrfRcsEl6yvxnmTrzRB-U_zF-tff07qLw04dIjHJMv6S5KS_pDtdJgkd2rNXEYUdJ8tQHx7rDJEesfNn469p9X2g_o6sSV7la0jD/s1600/20180927_190607.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7CE81mmHPbRR4L5Suyh2Tnwf7tqQ4vquF22rEzZUISrfRcsEl6yvxnmTrzRB-U_zF-tff07qLw04dIjHJMv6S5KS_pDtdJgkd2rNXEYUdJ8tQHx7rDJEesfNn469p9X2g_o6sSV7la0jD/s640/20180927_190607.jpg" width="640" height="360" data-original-width="1600" data-original-height="900" /></a></div>
<p>The August Hall was a great venue. Including a bowling alley and mini arcade downstairs.</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Some bowling with <a href="https://twitter.com/shunkosa?ref_src=twsrc%5Etfw">@shunkosa</a> and <a href="https://twitter.com/jan_vdv?ref_src=twsrc%5Etfw">@jan_vdv</a> at the <a href="https://twitter.com/quip?ref_src=twsrc%5Etfw">@Quip</a> party before Macklemore comes on. <a href="https://t.co/dAyWjbutjj">pic.twitter.com/dAyWjbutjj</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1045517455408357378?ref_src=twsrc%5Etfw">September 28, 2018</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Macklemore with special guest <a href="https://twitter.com/SteveMoForce?ref_src=twsrc%5Etfw">@SteveMoForce</a> <a href="https://t.co/z7P5SibBCZ">pic.twitter.com/z7P5SibBCZ</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1045536856849281025?ref_src=twsrc%5Etfw">September 28, 2018</a></blockquote>
<h2 id="day4">Day 4</h2>
<h3>MuleSoft</h3>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Taking a RAML definition in <a href="https://twitter.com/MuleSoft?ref_src=twsrc%5Etfw">@MuleSoft</a> anypoint and creating a mock web service. Outputs an endpoint URL to call. Can also convert definition to the Open API format. <a href="https://twitter.com/hashtag/DF18?src=hash&ref_src=twsrc%5Etfw">#DF18</a> <a href="https://t.co/XPzo7uuPLT">pic.twitter.com/XPzo7uuPLT</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1045724665409224704?ref_src=twsrc%5Etfw">September 28, 2018</a></blockquote>
<hr/>
<h2 id="deploymentFish">Deployment Fish Bottle Openers</h2>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">I said I'd create a bespoke <a href="https://twitter.com/deploymentfish?ref_src=twsrc%5Etfw">@deploymentfish</a> bottle opener if <a href="https://twitter.com/SalesforceDevs?ref_src=twsrc%5Etfw">@SalesforceDevs</a> delivered the switch statement for Apex last year at <a href="https://twitter.com/hashtag/DF17?src=hash&ref_src=twsrc%5Etfw">#DF17</a>. They delivered, so I did too at <a href="https://twitter.com/hashtag/DF18?src=hash&ref_src=twsrc%5Etfw">#DF18</a>. Thanks <a href="https://twitter.com/slettehaugh?ref_src=twsrc%5Etfw">@slettehaugh</a><br>,<a href="https://twitter.com/ca_peterson?ref_src=twsrc%5Etfw">@ca_peterson</a>, and team. <a href="https://t.co/OdFH505GMZ">https://t.co/OdFH505GMZ</a> <a href="https://t.co/9ulWwlKL2M">https://t.co/9ulWwlKL2M</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1045077751403663360?ref_src=twsrc%5Etfw">September 26, 2018</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Highlights of <a href="https://twitter.com/Dreamforce?ref_src=twsrc%5Etfw">@Dreamforce</a> day 1 included meeting <a href="https://twitter.com/FishOfPrey?ref_src=twsrc%5Etfw">@FishOfPrey</a> and getting my own deployment fish. <br><br>What were your top <a href="https://twitter.com/hashtag/DF18?src=hash&ref_src=twsrc%5Etfw">#DF18</a> moments? <a href="https://t.co/CdYh1DbxZJ">pic.twitter.com/CdYh1DbxZJ</a></p>— Carl Brundage (@carlbrundage) <a href="https://twitter.com/carlbrundage/status/1044819624611762177?ref_src=twsrc%5Etfw">September 26, 2018</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">TIL that <a href="https://twitter.com/deploymentfish?ref_src=twsrc%5Etfw">@deploymentfish</a> are UV sensitive. <a href="https://t.co/0HZQYjHW3m">pic.twitter.com/0HZQYjHW3m</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1045390243841507329?ref_src=twsrc%5Etfw">September 27, 2018</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Forgot this in my shirt pocket. TSA initially thought it was some kind of blade or razor. Another reason I will always treasure my <a href="https://twitter.com/hashtag/DeploymentFish?src=hash&ref_src=twsrc%5Etfw">#DeploymentFish</a>. Thanks, <a href="https://twitter.com/FishOfPrey?ref_src=twsrc%5Etfw">@FishOfPrey</a>! <a href="https://t.co/INHcjkU3za">pic.twitter.com/INHcjkU3za</a></p>— peter chittum (@pchittum) <a href="https://twitter.com/pchittum/status/1045860337319333889?ref_src=twsrc%5Etfw">September 29, 2018</a></blockquote>
<h2>To catch up on</h2>
<ul>
<li><a href="https://success.salesforce.com/myagenda?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A0000022F5tQAE">Be An Efficient Salesforce Developer with VS Code</a> (<a href="https://www.youtube.com/watch?v=hw9LBvjo4PQ">Video</a>)</li>
<li>Change Data Capture</li>
</ul>
<h2>See Also</h2>
<ul>
<li><a href="https://www.salesforce.com/blog/2018/10/dreamforce-18-ultimate-content-guide.html">The Dreamforce 2018 Ultimate Content Guide</a></li>
</ul>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-62968412111201789492018-09-26T08:40:00.001+12:002020-11-19T20:58:22.101+13:00Dreamforce 2018 Presentation - Understand your Org shape via visualization of Metadata Component Dependencies<p>At Dreamforce this year I gave a <a href="https://success.salesforce.com/sessions?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WWXOQA4">theater presentation</a> on using the Metadata Component Dependency Pilot API along with <a href="https://gephi.org/">Gephi</a> to explore ways of untangling the "Happy Soup" that makes up a Salesforce org.</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Thanks <a href="https://twitter.com/FishOfPrey?ref_src=twsrc%5Etfw">@FishOfPrey</a> for your epic talk about visualization of metadata component dependencies <a href="https://twitter.com/hashtag/DF18?src=hash&ref_src=twsrc%5Etfw">#DF18</a> <a href="https://twitter.com/absi_nv?ref_src=twsrc%5Etfw">@absi_nv</a> <a href="https://t.co/IwMdgG6YZf">pic.twitter.com/IwMdgG6YZf</a></p>— Samuel Moyson (@SamuelMoyson) <a href="https://twitter.com/SamuelMoyson/status/1044758028568805376?ref_src=twsrc%5Etfw">September 26, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>In this post I'll cover the contents of that talk and expanded on some areas that I'd like to cover in more depth.</p>
<h2>Session recording</h2>
<iframe id="ytplayer" type="text/html" width="640" height="360"
src="https://www.youtube.com/embed/6sIRJSdoCqo?autoplay=0&origin=http://www.fishofprey.com"
frameborder="0"></iframe>
<h2>Why Visualize an Orgs Metadata?</h2>
<div class="separator" style="clear: both; text-align: center;">
<figure style="clear: right; float: right; background: #222222; -webkit-margin-start: 0px; -webkit-margin-end: 0px;">
<a href="https://en.wikipedia.org/wiki/Anscombe's_quartet" imageanchor="1" style="clear: margin-bottom: 1em;"><img border="0" src="https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Anscombe's_quartet_3.svg/425px-Anscombe's_quartet_3.svg.png" width="320" height="233" data-original-width="425" data-original-height="309"></a>
<figcaption>All four sets are identical when examined using simple<br>summary statistics, but vary considerably when graphed - <a href="https://en.wikipedia.org/wiki/Anscombe's_quartet">Source</a></figcaption>
</figure>
</div>
<p>If you've ever seen the <a href="https://en.wikipedia.org/wiki/Anscombe's_quartet">Anscombe's quartet</a> you'd know a compelling reason to visualize information in addition to straight out numerical analysis. Visualizations can reveal patterns and features in the data that otherwise might not be readily apparent.</p>
<p>Additionally, when we start drilling into <b>all </b>the metadata in an org and the relationships within that metadata we can very quickly be overwhelmed by the share volume of it. There can be thousands of metadata items and many more relationships between them.</p>
<h3 style="clear: both;">The Soup and the Polar Bear</h3>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzVDV3dVizqbTAlUUDDZDdv-_Xm1CeosV22cnWVvIevWyiQjey6SOT3O-Mc1GmMqGRApPzQ1Sm6QnfafG1pmWV6DrTrfKfV1KqZT9DwTvjwF4UxwQZWJA6oWAl2I8B3wKh2fJyFsThfSoK/s1600/HappySoupSlide.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzVDV3dVizqbTAlUUDDZDdv-_Xm1CeosV22cnWVvIevWyiQjey6SOT3O-Mc1GmMqGRApPzQ1Sm6QnfafG1pmWV6DrTrfKfV1KqZT9DwTvjwF4UxwQZWJA6oWAl2I8B3wKh2fJyFsThfSoK/s800/HappySoupSlide.png" width="750" data-original-width="1213" data-original-height="679"></a></div>
<p>The concept of the metadata in your production org existing as a <a href="https://youtu.be/Pf33nrsqZOc?t=5m37s">"Happy Soup"</a> was introduced at TrailheadDX 2017 by Wade Wegner. It describes the scenario where all the conceptual apps that make up your production org intermingle without any strongly defined boundaries between them. Essentially, the org becomes one big melting pot of metadata. This has been the status quo for some time now (if you ignore managed packages and the relatively new addition of Packaging 2.0).</p>
<div class="separator" style="clear: both; text-align: center;">
<figure style="clear: right; float: right; background: #222222; -webkit-margin-start: 0px; -webkit-margin-end: 0px;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL0SnTaBlyd_pYhWJvK09NOvMV9WnJm0aVJ2Kyuh10aEtk_GALUdvMWuLkzT0Fx6XEs7YogYbgkk8_w0gDmSQXP-xaP46BXYSCmcpMBy8hPm-FuOcrICUInMbM8KpfAzTEfRJ3QXoGmUbW/s1600/MarvellousMedicine.jpg" imageanchor="1" style="clear: margin-bottom: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL0SnTaBlyd_pYhWJvK09NOvMV9WnJm0aVJ2Kyuh10aEtk_GALUdvMWuLkzT0Fx6XEs7YogYbgkk8_w0gDmSQXP-xaP46BXYSCmcpMBy8hPm-FuOcrICUInMbM8KpfAzTEfRJ3QXoGmUbW/s400/MarvellousMedicine.jpg" width="400" height="400" data-original-width="628" data-original-height="628"></a>
<figcaption>Soup chef at work on your production org - a Marvelous Metadata Mixing Pot</figcaption>
</figure>
</div>
<p>Now, take one of the production orgs that I work in day-to-day as an example. It was forged <b>11 years ago</b> when the seasonal release logo was a polar bear and the API version was v8.0. Ever since then it's been accumulating metadata changes as multiple people have come and gone. Each person <!--(Soup Chef, if you will)--> leaving a distinct mark on the metadata that makes up that org.</p>
<p>Back to our soup metaphor, that org is a decade old soup. Different soup chefs have been mixing ingredients in via a pinch of declarative UI changes, a dash of changes sets, a smidgen of metadata API deploys, and maybe the odd unmanaged package thrown in for good measure. Over the years an org can seem less like a carefully conceived soup recipe and more like a marvelous concoction with everything thrown in and reacting together in weird and wonderful ways.</p>
<p>Which kind of leaves you wondering - If you were presented with just the resulting happy soup, how would you identify the ingredients that went into it and how they need to interact so you could replicate it again? How can we unmake the happy soup?</p>
<p>The goal of our metadata visualizations will be to use the minds ability to quickly perceive and derive meaning from details such as size, color, position, and proximity to find insights that might not be apparent in tabular data. That might sound complicated, but the objective is to make otherwise complicated relationships readily apparent.</p>
<blockquote>“By visualizing information, we turn it into a landscape that you can explore with your eyes. A sort of information map. And when you’re lost in information, an information map is kind of useful.” - <a href="https://www.ted.com/talks/david_mccandless_the_beauty_of_data_visualization/transcript?language=en">David McCandless</a></blockquote>
<p>So, we know we want to make visualizations of the metadata and the dependencies within, but where do we start gathering that data?</p>
<h2 style="clear: both;">The Metadata Component Dependency API</h2>
<p>Luckily for us the new Metadata Dependencies pilot introduced in Summer '18 at TrailheadDX allows for the use of Tooling API SOQL queries to quickly find dependencies between metadata components. You can signup for the pilot via your AE as per the release notes: <a href="https://releasenotes.docs.salesforce.com/en-us/summer18/release-notes/rn_metadata_metadatacomponentdependency.htm">Untangle Your Dependencies with MetadataComponentDependency Queries (Pilot)</a></p>
<p>The benefit of this pilot is that it is <i>much</i> faster and easier than trying to assemble the same information yourself. I've tried extracting similar details via the <code>ApexClassMember.SymbolTable</code>. While possible, it is a path that is thwart with multiple API calls per ApexClass. And at the end of all that you will still only have a fraction of the possible relationships covered.</p>
<p>Once you are in the pilot it is pretty simple to use. A single SOQL query can bring back the majority of relationships for an org. For example, using the Tooling API via the sfdx cli:</p>
<pre style="white-space: pre-wrap;">sfdx force:data:soql:query --usetoolingapi --query "SELECT MetadataComponentId, MetadataComponentName, MetadataComponentType, RefMetadataComponentId, RefMetadataComponentName, RefMetadataComponentType FROM MetadataComponentDependency Where RefMetadataComponentType = 'CustomField'" -u devorg</pre>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2f09XXe_88O83uoNrCWdoANRoeeaGj08VoEtu6X3StQbhrOsMnfm9GRcRX7-L7yFC0i5qIk6BkZHhcj0iKRy56yzBbushZEQ7Ajaj2PktgmvJPcTXZh3uiGW33d-4PdhULAsIJ52GvO3n/s1600/SoqlQuery.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2f09XXe_88O83uoNrCWdoANRoeeaGj08VoEtu6X3StQbhrOsMnfm9GRcRX7-L7yFC0i5qIk6BkZHhcj0iKRy56yzBbushZEQ7Ajaj2PktgmvJPcTXZh3uiGW33d-4PdhULAsIJ52GvO3n/s1600/SoqlQuery.png" width="760" data-original-width="1600" data-original-height="540"></a>
<!--a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5Yw_SJZdFb1E-gfirPFAJzAdyYYuQFEg40v_A2LH32u6MK0re8TV6JH5qnGej-TTrgbeHatJ06JEkFuMi3SdbScHutZ8fDyIrhQLj0OtseMDQXX56V3yh9vYPQXQAg4BqlkxS4B37KRY2/s1600/SOQLUsage.gif" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5Yw_SJZdFb1E-gfirPFAJzAdyYYuQFEg40v_A2LH32u6MK0re8TV6JH5qnGej-TTrgbeHatJ06JEkFuMi3SdbScHutZ8fDyIrhQLj0OtseMDQXX56V3yh9vYPQXQAg4BqlkxS4B37KRY2/s1600/SOQLUsage.gif" width="760" data-original-width="1600" data-original-height="612" /></a-->
<h3>Supported Dependencies</h3>
<p>As this is a pilot feature the types of dependencies it can reveal isn't 100% yet. Below is a small subset of what can and can't be tracked: (as at the time of posting) </p>
<table border="1">
<tbody><tr><th>Type</th><th>Used Id</th><th>Supported</th></tr>
<tr><td>CustomObject</td><td>Apex Class</td><td>✅</td></tr>
<tr><td>CustomObject</td><td>Process Builder</td><td>✅</td></tr>
<tr><td>CustomObject</td><td>Lookup Relationship Field</td><td>❌</td></tr>
<tr><td>CustomObject</td><td>Reports</td><td>❌</td></tr>
<tr><td>CustomField</td><td>Layout</td><td>✅</td></tr>
<tr><td>CustomField</td><td>Reports</td><td>❌</td></tr>
<tr><td>Flow</td><td>Process Builder</td><td>✅</td></tr>
<tr><td>Flow</td><td>Flow</td><td>❌</td></tr>
</tbody></table>
<p>You can see the complete list of supported metadata relationships in <a href="https://github.com/afawcett/dependencies-sample">https://github.com/afawcett/dependencies-sample</a></p>
<h3>Augmenting the Graph</h3>
<p>Using the results from the Metadata Component Dependency query as a starting point we can then augment the resulting graph with additional metrics. Here are some of the additional details that can be merged in as meta-metadata.</p>
<ul>
<li>CustomField.Metadata - can be used to show lookup relationships</li>
<li>ApexClass.ApiVersion - useful for finding Apex classes with mismatched API versions</li>
<li>The code coverage results for each Apex class</li>
<li>The number of lines of code in each Apex Class</li>
<li>Where available, the created date for the Metadata</li>
<li>The number of records in a CustomObject</li>
<li>The number of Triggers per sObject</li>
</ul>
<h2>Tooling to create the Dependency Graph</h2>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGY0m2z0r4wkcXJJxiMUAQ2xnARhunncYCfz4GqM5CNv2jbaw5QMkYNe8q4FhoZMOfY1QAS-IGdnwXGiT2KJU9whu1w1qoIKeaZO8Auo_1hmAuwmnlrkzMrUPP-ubylRgM5fa8BAMXWyWV/s1600/PathToVisualization.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGY0m2z0r4wkcXJJxiMUAQ2xnARhunncYCfz4GqM5CNv2jbaw5QMkYNe8q4FhoZMOfY1QAS-IGdnwXGiT2KJU9whu1w1qoIKeaZO8Auo_1hmAuwmnlrkzMrUPP-ubylRgM5fa8BAMXWyWV/s800/PathToVisualization.png" width="760" data-original-width="1600" data-original-height="900"></a>
<p>The first part of the visualization process will be to query the MetadataComponentDependency records and convert the results into a graph. I didn't go into this step in any detail in my talk as it isn't very interesting to watch. At it's simplest, you can use one of the following options.</p>
<h3>CLI Generation of the Gephi graph</h3>
<pre style="white-space: pre-wrap;">NOTE: At the time of publishing the Github repo wasn't fully up to date with the latest public build. I'll aim to have this done shortly after Dreamforce.</pre>
<p>Run the following command:</p>
<pre>sfdx fitdx:dependencies:report -u DeveloperOrg > DeveloperOrg.gexf</pre>
<p>And that's pretty much it. The command from the <a href="https://github.com/FuseInfoTech/FitCLI">FitCLI</a> plugin will run the query, build the graph, and export it ready for opening in Gephi. You only need to point it at the correct Salesforce Org and redirect the output into a file.</p>
<p>If you want to add the augmented graph metrics you can supply the <code>-a</code> option. Note that this will take <i>significantly longer</i> to complete as it involves a number of additional tooling API queries. It's also beneficial to run all the Apex Tests before exporting the graph so it has complete coverage details.</p>
<h3 name="GUI">GUI option for creating the Gephi file</h3>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu6spUXKjZikSicRUM1hov_3QX67ewb1lWlQrZLji8uCEq-bI7s-JpbqTu0rrKnZCNdM1b6LEL5l15cZy9pA7U-J6bptiXBKFPSJVUdZwz0rkA5XGGnTCuy8pt_XqgFnqFoKYfegAxh5MX/s1600/MetadataDependencies.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu6spUXKjZikSicRUM1hov_3QX67ewb1lWlQrZLji8uCEq-bI7s-JpbqTu0rrKnZCNdM1b6LEL5l15cZy9pA7U-J6bptiXBKFPSJVUdZwz0rkA5XGGnTCuy8pt_XqgFnqFoKYfegAxh5MX/s800/MetadataDependencies.PNG" data-original-width="852" data-original-height="154" width="750"></a></div>
<p>As an alternative to using the command line you can also using the <a href="https://www.fuseit.com/explorer">FuseIT SFDC Explorer</a> from v3.10 onwards. This now includes the <b>Metadata Dependencies</b> tab to generate Gephi file. It's pretty much exactly the same as the command line version and will prompt for where you want to save the resulting file.</p>
<p>Ideally with either the CLI or the GUI options the target org will have access to <code>MetadataComponentDependency</code> records. If that isn't the case you can still use the augmented option to get some graph details. It won't be as fast or as complete, but you will get a good deal of the relationships based on other data exposed via the Tooling API.</p>
<!--p>Note that you can still use the graph generation tooling below without access to the pilot. It won't be as fast or as complete, but you will get a good deal of the relationships based on other data exposed via the Tooling API.</p-->
<h2>Examples</h2>
<p>Now we can get into the interesting part of loading the graphs into <a href="https://gephi.org/">Gephi</a> to see what we can discover. You can open the <code>.gexf</code> files directly into Gephi and then start manipulating them. </p>
<!--details on the filters being applied-->
<p>This video quickly goes through the Field Usage and Packages examples that are expanded on below.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/tDerY7OpSp4" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
<h3>Field Usage</h3>
<p>Lets say we want to find what will be impacted if changes are made to the <code>Property__c.Address__c</code> field in the <a href="https://github.com/forcedotcom/sfdx-dreamhouse">Dreamhouse app</a>. The steps would be as follows:</p>
<ol>
<li>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgl89-QzlEY9L51KbxtRfGt5yJHnc1ml2zCqmLeFwrYmtLqf72NgJvgZaPYx2f588DCS59-fWW_rt6I-wsjjBSFGZLsePjkX7YMx6qbB_AI40ORuzd__u1E_SlARA4O1cUtWrYdkP2PDbO-/s1600/FIeldUsage_PartitionByType.PNG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgl89-QzlEY9L51KbxtRfGt5yJHnc1ml2zCqmLeFwrYmtLqf72NgJvgZaPYx2f588DCS59-fWW_rt6I-wsjjBSFGZLsePjkX7YMx6qbB_AI40ORuzd__u1E_SlARA4O1cUtWrYdkP2PDbO-/s400/FIeldUsage_PartitionByType.PNG" width="221" height="400" data-original-width="251" data-original-height="455"></a></div>
Partition the Node color by Type. This will make it more apparent what type of nodes you are looking at.
</li>
<li style="clear: both;">
<div class="separator" style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTv3-myRBaG6yed5IxZqrk29yKLrkd6nfdIjqRZ0TDgE1XUBG5HHHlO4QAWykg_EPGgTeIhgBkSV5TqSFy6-MyIbCwI1_0UaC4PD69p_4i8Uz6SoNh8Q-Y8qnBGNv2bQMPVJpiR63sye0J/s1600/FIeldUsage_NetworkDiameter.PNG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTv3-myRBaG6yed5IxZqrk29yKLrkd6nfdIjqRZ0TDgE1XUBG5HHHlO4QAWykg_EPGgTeIhgBkSV5TqSFy6-MyIbCwI1_0UaC4PD69p_4i8Uz6SoNh8Q-Y8qnBGNv2bQMPVJpiR63sye0J/s400/FIeldUsage_NetworkDiameter.PNG" width="400" height="360" data-original-width="229" data-original-height="206"></a>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjq3h4YThqwSoXZopqDoztRxx-t9zEV9G63rgT7G9aLaGNdZdvosq-HmTl8xVmMRI7Sqh9PyYUNS2xbaF9Aj9SXUnH-diTviZ_bLEB-9t1rK8NBheht6k36XDNoLpL8CuZkicFDwTmzXDFA/s1600/FIeldUsage_FieldSize.PNG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjq3h4YThqwSoXZopqDoztRxx-t9zEV9G63rgT7G9aLaGNdZdvosq-HmTl8xVmMRI7Sqh9PyYUNS2xbaF9Aj9SXUnH-diTviZ_bLEB-9t1rK8NBheht6k36XDNoLpL8CuZkicFDwTmzXDFA/s400/FIeldUsage_FieldSize.PNG" width="400" height="232" data-original-width="252" data-original-height="146"></a></div>
Size the nodes based on the <b>Betweenness Centrality</b>. Which is a fancy way of saying "make the nodes that appear on the shortest paths between other nodes bigger". This is one possible indication of how important a node is to all the other nodes in the graph. Before we can do this we need to run the <b>Network Diameter</b> statistics.
</li>
<li style="clear: both;">
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8BTb7rdPs7n7yYZ7ppUXLw7awOagU6WUbgAHnnt-kM0VVsC_FUJ9uU1VvCSr4uhT7oEhlKazGTm9MbBHNZhkIvXAjV5X8r0DEYKhi_NjhiQtbRDSBFQc5mEprVGsjAC2XgvcG86aVRmph/s1600/FIeldUsage_Layout.PNG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8BTb7rdPs7n7yYZ7ppUXLw7awOagU6WUbgAHnnt-kM0VVsC_FUJ9uU1VvCSr4uhT7oEhlKazGTm9MbBHNZhkIvXAjV5X8r0DEYKhi_NjhiQtbRDSBFQc5mEprVGsjAC2XgvcG86aVRmph/s400/FIeldUsage_Layout.PNG" width="306" height="400" data-original-width="249" data-original-height="325"></a></div>
Apply a layout to arrange the nodes. I've used the "Force Atlas" layout with the <i>Repulsion strength</i> set to 1500 and <i>Adjust by Sizes</i> checked.
</li>
<li>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi07FShGBdRNFh7pq33urVXV-HlE-TYgGyCZHwOMI-8M5FdZ8B4TfL5zLfRC1MfP4ecdDLZUxPPXl1-L9ZfHjqM936TmWJlIiAAHzo6-5A2N0y-0-0E2cw8V9uBSO3dBayTjnJ00C3WaKzb/s1600/FIeldUsage_ShowNodeLabels.PNG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi07FShGBdRNFh7pq33urVXV-HlE-TYgGyCZHwOMI-8M5FdZ8B4TfL5zLfRC1MfP4ecdDLZUxPPXl1-L9ZfHjqM936TmWJlIiAAHzo6-5A2N0y-0-0E2cw8V9uBSO3dBayTjnJ00C3WaKzb/s400/FIeldUsage_ShowNodeLabels.PNG" width="400" height="38" data-original-width="544" data-original-height="52"></a></div>
Show the Node Labels and scale to fit
</li>
<li><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-4_UNzFEfMmEAAw40GjjnaYEXc2YPEFsoE4Agc8B6o0-TtsPGRG-XQYQk6hYcl2Ljh21T7hXBA6wn7fc_h1MasU6ciQRNyfFsxCiUfMQtQU0mwybdOb3UD8975TqGK5Cb-zNXgduq25gN/s1600/FieldUsage_Address.PNG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-4_UNzFEfMmEAAw40GjjnaYEXc2YPEFsoE4Agc8B6o0-TtsPGRG-XQYQk6hYcl2Ljh21T7hXBA6wn7fc_h1MasU6ciQRNyfFsxCiUfMQtQU0mwybdOb3UD8975TqGK5Cb-zNXgduq25gN/s400/FieldUsage_Address.PNG" width="400" height="74" data-original-width="1038" data-original-height="192"></a></div>
Switch to the <b>Data Table</b> window and filter to the Address field.
</li>
<li><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTnqphaqDtEnMukNmEvE_2WB2IAGZq-o-ix7-t2CZj8Y5MvpSxcYGL9iE-usS8BukiOIaWSR2miDeiNTNUcTNPX5OjP0DayT9fTQne1Cgdj7PO_NHBUj9Le6_o3tO-AV5Ft1rViQvwB6Tx/s1600/FieldUsage_AddressUsage.PNG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTnqphaqDtEnMukNmEvE_2WB2IAGZq-o-ix7-t2CZj8Y5MvpSxcYGL9iE-usS8BukiOIaWSR2miDeiNTNUcTNPX5OjP0DayT9fTQne1Cgdj7PO_NHBUj9Le6_o3tO-AV5Ft1rViQvwB6Tx/s400/FieldUsage_AddressUsage.PNG" width="400" height="215" data-original-width="693" data-original-height="373"></a></div>
Zoom out a bit, and you will be able to see the the Metadata that references the Property__c.Address__c field.</li>
</ol>
<!-- TODO Link to Dreamhouse example gexf file -->
<h3 style="clear: both;">Potential Packages</h3>
<ol>
<li>Run the "Modularity" Statistics. This algorithm will look for metadata communities based on the dependencies between them. You can adjust the <b>Resolution</b> up or down if you want more or less communities.</li>
<li>Change the appearance of the Nodes to be partitioned by the resulting "Modularity Class". With the correct resolution and layout it will given you a reasonable guide to where potential packages are located. You will likely need to make some finer adjustments along the boundaries.</li>
<li>One way to export the nodes for the package is to select them and then copy to a new workspace. The new data table can then be exported as a csv.<br/> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyq6zTUvmwc5caHwy9-nwnMwd-8ks2Zvrd0lBECn6B080Drq2BHUX4ovz5dN_lORSa3d88JRFUMBquThZKe3f6yBRFkb_0yHlfaXAOiG4p7GAEEQ7ZjWtu1N1ngybX9GXYGg2Q37z5v40N/s1600/ExportSelectedNodes.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyq6zTUvmwc5caHwy9-nwnMwd-8ks2Zvrd0lBECn6B080Drq2BHUX4ovz5dN_lORSa3d88JRFUMBquThZKe3f6yBRFkb_0yHlfaXAOiG4p7GAEEQ7ZjWtu1N1ngybX9GXYGg2Q37z5v40N/s320/ExportSelectedNodes.png" width="320" height="189" data-original-width="536" data-original-height="316" /></a> </li>
</ol>
<h3 style="clear: both;">API Versions</h3>
<iframe width="560" height="315" src="https://www.youtube.com/embed/vfj0tNEWBsA" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
<ol>
<li><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgItn3gK4cfoTjt3BObStDM-MNuyuqAIDM09uq42DtDRdoMKh-mNoN7xE9hsLtV8_AzV7E9tgC5aKky1HBlrTFrBniN9GyjelGu5FBPx2qOZBe1yDp3sc1rguV4TYPIEZVqM-cngOUr2d3Z/s1600/ApiVersionFilter.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgItn3gK4cfoTjt3BObStDM-MNuyuqAIDM09uq42DtDRdoMKh-mNoN7xE9hsLtV8_AzV7E9tgC5aKky1HBlrTFrBniN9GyjelGu5FBPx2qOZBe1yDp3sc1rguV4TYPIEZVqM-cngOUr2d3Z/s320/ApiVersionFilter.png" width="225" height="320" data-original-width="251" data-original-height="357" /></a>
Filter to just those bits of metadata that have an API version defined. One way to do this is to drag a "Non-null (ApiVersion)" filter down onto the Queries.</li>
<li>Under <b>Appearance > Nodes</b>, set the node size to rank by <b>Degree</b>. The degree is a measure of how many edges go in or out of the node. So more connected nodes will be larger.</li>
<li>Set the Nodes color to be ranked by API version. Choose a color pallete that emphasizes lower API versions as being problematic.</li>
<li>Set the Node Label to "API Version" and size as required.</li>
</ol>
<h3 style="clear: both;">Code Coverage</h3>
<iframe width="560" height="315" src="https://www.youtube.com/embed/bUL4Cr4fIns" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
<ol>
<li>Size the nodes by "LengthWithoutComments" to give an indication of how much code is in each Apex class.</li>
<li>Color the nodes by ranking of the "PercentCovered". Use the slider to roughly indicate code with 75% coverage.</li>
<li>It can be useful to filter to just the test classes and assign them a different node color. They won't have any coverage themselves.</li>
<li>Set the node label to the "PercentCovered"</li>
<li>A circular layout sorted by the coverage percent can be useful to separate out the problem nodes. Move the text classes into a seperate ring so you can see the relationships between the tests and the classes they cover.</li>
</ol>
<h3 style="clear: both;">Classes with excessive lines of code</h3>
<p>As an experiment I drastically increased the amount of node scaling that was possible. This can really emphasis the differences in the size of Apex classes.</p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-g0Zr2PvYNXndCJj-U_BRHnbLm8gAg3jbdxwxQZumKpjiA13h2zptuh23MSnm-WSnusmu3OrJfL0eNaUgxQ9iHUrShxe-AtgBj21ujKETnKWZpBAhWPdLzra61qqGAbswZE7IP8dMnIdO/s1600/LengthWithoutComments.PNG" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-g0Zr2PvYNXndCJj-U_BRHnbLm8gAg3jbdxwxQZumKpjiA13h2zptuh23MSnm-WSnusmu3OrJfL0eNaUgxQ9iHUrShxe-AtgBj21ujKETnKWZpBAhWPdLzra61qqGAbswZE7IP8dMnIdO/s320/LengthWithoutComments.PNG" width="280" height="320" data-original-width="703" data-original-height="802" /></a>
<!--
TODO:
import Org health report details
import lightning readiness report
# of records on custom objects
import actual live records rather than just metadata
Visualize Test Case failures - see areas where failures are occurring
Triggers per sObject - aim for only one
Track cascading impacts of a change to a field.
Paint Tool for neighoubous and neibours of neigbours.
Heatmap tool
Metric - test execution time
-->FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-68125349216410115512018-08-24T12:13:00.001+12:002018-09-22T21:17:28.254+12:00Dreamforce 2018 Session picks<p>Here are some of my current picks for Dreamforce 2018 sessions. I'm aiming for a mix of developer related topics in areas I want to learn more about plus anything that sounds informative. It isn't an exhaustive list and there are certainly some other session that I'll be adding.</p>
<h1>Most important session that I'm definitely going to attend</h1>
<p>I might be biased, but this session is on my must attend list.</p>
<p>Tell your friends, tell your neighbors, tell your family, bring your mum along. There will be something for everyone!<br/>
Who doesn't like pretty pictures, metadata, and a sprinkling of graph theory?</p>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WWXOQA4">Understand your Org shape via visualization of Metadata Component Dependencies</a>
<!--blockquote>When moving to Salesforce DX unlocked packages you need a fast and easy way to identify the modules that make up a Salesforce org and how they are related to each other. This also applies when needing insight into how a specific field is used by other components.
By using MetadataComponentDependency queries along with Gephi, an open-source visualization and exploration tool for graphs, we can rapidly untangle the dependencies via a range of layouts and metrics. These interactive visualizations aid developers in understanding the shape of a Salesforce org, leading to benefits as migrating Visualforce pages to Lightning components and identifying potential packages from complex metadata relationships.</blockquote-->
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Learn how to visualize the ingredients in your <a href="https://twitter.com/hashtag/Salesforce?src=hash&ref_src=twsrc%5Etfw">#Salesforce</a> Orgs "Happy Soup" via my <a href="https://twitter.com/Dreamforce?ref_src=twsrc%5Etfw">@Dreamforce</a> session using MetadataComponentDependency queries:<br><br>"Understand your Org shape via visualization of Metadata Component Dependencies"<br><br> <a href="https://twitter.com/hashtag/DF18?src=hash&ref_src=twsrc%5Etfw">#DF18</a> <a href="https://t.co/0W4KM1ald1">https://t.co/0W4KM1ald1</a> <a href="https://t.co/tKxyqWy4gM">pic.twitter.com/tKxyqWy4gM</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/1031345907877392384?ref_src=twsrc%5Etfw">August 20, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</li>
</ul>
<h2>Keynotes</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WYWsQAO">Salesforce for Developers Keynote</a></li>
</ul>
<h2>Meet The *'s</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WYXRQA4">Parker Harris' True to the Core: What's Next for Our Core Products</a> - Expect a focus on reinvigorating the idea exchange.</li>
<li>Meet the Developers - currently MIA?</li>
<li>Meet the Apex Engineering and Product Team - currently MIA?</li>
</li>
</ul>
<h2>Apex</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WZTXQA4">Everything that's Awesome with Apex</a>
<blockquote>Get a sneak peak into Apex plans, roadmap and how we are making secure development easier. We'll share some of our newest concepts <b>(async Apex anyone?)</b> and get your feedback on hot IdeaExchange features.</blockquote>
👀Async Apex, maybe something to help with FLS and CRUD in managed packages. Yes please!
</li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WXVIQA4">Test Your Visual Workflow and Process Builder Automations</a>. I'm assuming there will be some Apex involved in this testing process. </li>
</ul>
<h2>APIs</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WZU7QAO">Creating Massive Adoption for Your APIs</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WVcQQAW">The New User Interface API</a></li>
</ul>
<h2>Salesforce DX</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WUY5QAO">Super Session: Salesforce DX</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WVyWQAW">Advanced Techniques To Adopt Salesforce DX Unlocked Packages</a></li>
</ul>
<h2>IDE</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WZTjQAO">Building Powerful Tooling for IDEs Through Language Servers</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WZTbQAO">Banish the Bugs with the Apex Replay Debugger</a></li>
</ul>
<!--h2>Peeking under the hood</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00000stRRuUAM#/session/a2q3A000001ytGEQAY">New Apex Compiler Rollout</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00000stRRuUAM#/session/a2q3A000001pwnDQAQ">How We Do the Magic We Do - A Peek into Multi-tenancy</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00000stRRuUAM#/session/a2q3A000001yuLjQAI">SOQL: Performance Explained</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00000stRRuUAM#/session/a2q3A000001ytGCQAY">How Salesforce does Incremental Code Deploys for internal orgs</a></li>
</ul-->
<h2>Platform Events</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WZTtQAO">Synchronize Data and Orchestrate Workflows in Real-Time with Change Data Capture</a></li>
</ul>
<h2>Platform</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WUYBQA4">The Lightning Platform Roadmap - Part I</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WUYCQA4">The Lightning Platform Roadmap - Part II</a></li>
</ul>
<h2>Einstein / AI</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WYhfQAG">BREAKING NEWS: The Latest Developments and Roadmap for Einstein</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WWiCQAW">Einstein Vision - How To Train Your AI Like An Expert!</a></li>
</ul>
<h2>Security</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WX4qQAG">Avoiding Common Security Mistakes</a></li>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WYwMQAW">Automated Code Quality & Security with CodeScan</a></li>
</ul>
<h2>Fun</h2>
<ul>
<li><a href="https://success.salesforce.com/sessions?eventId=a1Q3A00001XoCSUUA3#/session/a2q3A000001WZCpQAO">Flood the Trailblazer Community Cove: Swag & Sticker Meetup</a><br/>Got too much swag or something you can't get home - swap it! Last year I gave a bunch of stuff away that I'd collected but couldn't actually put in my luggage. I'm looking at you oversized Codey. And the rose seed in soil that NZ customs would have opinions on.</li>
</ul>
<h2>Lightning</h2>
<ul>
<li>TODO - Need something to fill out this area to be a well rounded developer. Lightning Roadmap maybe?</li>
<li></li>
</ul>
<!--René Winkelmeyer-->
<h2>See also</h2>
<ul>
<li>My <a href="http://www.fishofprey.com/2016/08/dreamforce-2016-session-picks-and.html#tips">General Dreamforce Tips</a> from last year</li>
<li>
Salesforce Engineering: <a href="https://engineering.salesforce.com/your-dreamforce-agenda-for-developers-118d7b6ad90">Your Dreamforce [2018] Agenda for Developers</a></li>
</ul>
FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-7212195425370311862018-07-23T12:16:00.000+12:002018-07-23T12:17:09.871+12:00FuseIT SFDC Explorer 3.9.18190.1 - Summer '18<p>Another roundup of some of the changes to the <a href="http://www.fuseit.com/explorer">FuseIT SFDC Explorer</a> since the <a href="http://www.fishofprey.com/2017/08/fuseit-sfdc-explorer-36171841-and.html">3.7.17230.1</a> release.</p>
<h2>Display additional columns for the Apex Log timeline (Experimental)</h2>
<p>Let's say you just ran all the tests in your org in parallel and captured the debug logs for each transaction. Now you have a huge number of debug logs to peruse, but where to start?</p>
<p>Experimental features that I've only tried a few times to the rescue!</p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVTdk5eHDTaYAKkwe8yZ19ToqUidVUuel6K7QkzgMgG4w_FnOa0kvkD51V_wqWf_Z30D8cxj9PaYt85iM4ce_o_NxsQvcfi360VabLEazSkOP5lxwRuURCW6AaxfFyWxeIRnqOrjgLpCk1/s1600/LogTimelines.PNG" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVTdk5eHDTaYAKkwe8yZ19ToqUidVUuel6K7QkzgMgG4w_FnOa0kvkD51V_wqWf_Z30D8cxj9PaYt85iM4ce_o_NxsQvcfi360VabLEazSkOP5lxwRuURCW6AaxfFyWxeIRnqOrjgLpCk1/s800/LogTimelines.PNG" width="760" data-original-width="1025" data-original-height="428" /></a>
<p>By double clicking in the Timeline column cells the full debug log will be pulled down and converted to a timeline. I'm still experimenting with this. Certainly having all the timelines shown at different scales is a bit problematic. It's hard to get a sense of how long the actual transaction took relative to the adjacent ones.</p>
<p>I might instead take a different approach here and extract some metadata from the debug log and just show the core details. I'd look for things like hitting limits, throwing exceptions, slow DML, etc...</p>
<h2 name="deleteAllLogs" id="deleteAllLogs">Button to delete ALL ApexLog's in an org.</h2>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuDAdF52uOHxFl0gZ6dsqmz2LI4sSAVdRxPnAVtr9o_w06LbkLccWbxZ3FFm4aZdg5Lk31sZ4RbQ3ezCyWhDjwii6mh90ldDholjgLHUqVWNhe5mUP-QDZyoL89LPdEfBAJFVTOkAQq_fG/s1600/DeleteAllApexLogs.PNG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuDAdF52uOHxFl0gZ6dsqmz2LI4sSAVdRxPnAVtr9o_w06LbkLccWbxZ3FFm4aZdg5Lk31sZ4RbQ3ezCyWhDjwii6mh90ldDholjgLHUqVWNhe5mUP-QDZyoL89LPdEfBAJFVTOkAQq_fG/s320/DeleteAllApexLogs.PNG" width="320" height="178" data-original-width="142" data-original-height="79" /></a></div>
<p>It's a small thing, but currently with Summer '18 it is all to easy to run into a message like:</p>
<blockquote>
The Developer Console didn't set the DEVELOPER_LOG trace flag on your user. Having an active trace flag triggers debug logging. You have 318 MB of the maximum 250 MB of debug logs. Before you can edit trace flags, delete some debug logs.
</blockquote>
<p>Then you get to play a game of whack-a-<strike>mole</strike>ApexLog with the Tooling API to clear them all out and then get on with your day. This button on the Apex Logs tab reduces it to a single click.</p>
<p>You might also like to vote for the idea: <a href="https://success.salesforce.com/ideaView?id=0873A000000TwBDQA0">Allow TraceFlags to indicate that Debug logs can be deleted automatically</a>. Adding a TTL and automatic purge of older logs would avoid most of these issues while still being flexible if you needed longer term logging.</p>
<h2 style="clear:both;">Show total counts per log category</h2>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1IYPdwxz3ZjYH6DSQ9uwEOwsLvynGJSb_o7QLTEQu_bL8-XX-TEfEDKpKUdLOYhUtAZtYvZDAMors4-OiRx00lMckuwg9Z1A87j3Q1gT5Ps6N0ic4e5OMacu2jS1Ivt6PEqsYYYdAcQbO/s1600/LogCategoryPercentages.PNG" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1IYPdwxz3ZjYH6DSQ9uwEOwsLvynGJSb_o7QLTEQu_bL8-XX-TEfEDKpKUdLOYhUtAZtYvZDAMors4-OiRx00lMckuwg9Z1A87j3Q1gT5Ps6N0ic4e5OMacu2jS1Ivt6PEqsYYYdAcQbO/s640/LogCategoryPercentages.PNG" width="760" data-original-width="859" data-original-height="25" /></a>
<p>The percentage that each log category contributes to the overall log size has been added to the footer. This can be useful for adjusting the log levels when the logs are getting too noisy or large.</p>
<h2 style="clear:both;">Skip Code Coverage</h2>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9vmK2YjuaregXL0sQjMIPuIei0KKb_1rohUlQWXNmqKFv9qtdOUjAAb3IEu3dWKM16lE8ndwsMxdfJl60s7mAGEecjFU1fognj6QxdrEx5KRXN6cR3-QYjRhBifd6UNbmcrEmsKNHhDV8/s1600/SkipCodeCoverage.PNG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9vmK2YjuaregXL0sQjMIPuIei0KKb_1rohUlQWXNmqKFv9qtdOUjAAb3IEu3dWKM16lE8ndwsMxdfJl60s7mAGEecjFU1fognj6QxdrEx5KRXN6cR3-QYjRhBifd6UNbmcrEmsKNHhDV8/s400/SkipCodeCoverage.PNG" width="400" height="122" data-original-width="268" data-original-height="82" /></a></div>
<p>With <a href="https://releasenotes.docs.salesforce.com/en-us/summer18/release-notes/rn_apex_opt_out_code_coverage.htm">Summer '18 it is possible to opt out of collecting code coverage with a test run</a>. This can save some time when running the test cases if you don't require the coverage data.</p>
<h2 style="clear:both;">Additional metadata deployment details</h2>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-hLwFShMUK9PT8AaTEHNzycxcHVp9deRx_GIChxzmIYJdTQcFh6HN04ZRhIMSy4g_fwmK9rjAnrpOeISFsIEW_JmJHQ-sfCgoP7GwqWO5d3XMRpe8uCEumIfOKdU13wLpQ0kQRE4GA6Oi/s1600/MetadataDetails.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-hLwFShMUK9PT8AaTEHNzycxcHVp9deRx_GIChxzmIYJdTQcFh6HN04ZRhIMSy4g_fwmK9rjAnrpOeISFsIEW_JmJHQ-sfCgoP7GwqWO5d3XMRpe8uCEumIfOKdU13wLpQ0kQRE4GA6Oi/s320/MetadataDetails.png" width="320" height="101" data-original-width="564" data-original-height="178" /></a>
<p>When selecting individual metadata files to deploy details such as path, local file system data modified, and CRC are displayed.</p>
<h2 style="clear:both;">Other changes 3.9</h2>
<ul>
<li>ApexLogContentControl - Format "SkippedBytesOfDetailedLog". Shortcut to line. Protected against parsing multiple log models at the same time.</li>
<li>Expose the Duration in the ApexLogTreeViewUserControl. Color code the Event column</li>
<li>ApexLogEntry - Prevent recursion in the model. New properties for Text, Message. Dedicated LimitUsageForNsApexLogEntry ApexLogEntry</li>
<li>Option to display timeline bookmarks over thumbs. Detect and highlight LimitUsage warnings and highlight in timeline. Display log running events (> 500ms) as lines in the timeline.</li>
<li>Make CSV field name checking case insensitive.</li>
<li>When searching for a term in a debug log, ensure that line scrolls into view.</li>
<li>When listing Apex classes include an "Uncovered Lines" column</li>
<li>Emphasize the Warning and Error entries with larger bars</li>
<li>ApexLogModel: Handle CODE_UNIT_STARTED for Validation. Reparent when transitioning from CUMULATIVE_LIMIT_USAGE_END to CODE_UNIT_STARTED without intermediate CODE_UNIT_FINISHED</li>
<li>PackageCreation - Include additional metadata when performing a HashDiff on a folder.</li>
<li>WSDL2Apex: Skip Complex Content Restrictions (with a warning) rather than throw an exception.</li>
<li>WSDL2Apex: Reset stored web service metadata between runs.</li>
<li>ApexLogService - Expand LogMessage enum with missing records</li>
<li>Update SalesforceSession to use Summer '18 v43.0 API version</li>
<li>T4 Code Generator - Allow for sObjects with no record types defined</li>
<li>SalesforceSession - Support for visualforce.com as a SOAP Partner URL</li>
<li>SalesforceServiceWrapper - Improve performance of ObjectTypeFromId(string id) for looking up the sObject type based on the keyprefix. EntityServiceGenerator.tt - Don't include a custom objects keyPrefix in RegisterKeyPrefixObjectType by default.</li>
<li>Include dedicated columns when listing Apex classes for Lines covered and Total lines</li>
<li>ApexClassService - Handling missing SOSL search results when looking for test classes.</li>
<li>MetadataServiceWrapper - include support for deployment of permissionsets</li>
<li>SalesforceException - Log direct web request with cookie exceptions.</li>
<li>Wsdl2Apex - handle services that require specific casing on the service URL query string</li>
<li>ToolingServiceWrapper - Check for API access to sObjects ApexOrgWideCoverage and ApexCodeCoverageAggregate before querying.</li>
</ul>
<h2>Other changes 3.8</h2>
<ul>
<li>Data Export Console: Support for connection strings using RefreshTokens rather than usernames and passwords.</li>
<li>Options to metadata deploy Aura components</li>
<li>Apex Test Results - Expand nodes to show test case failures initially.</li>
<li>UI - Improve menu overflow options</li>
<li>UI - Track selected log event as the DataGrid scrolls</li>
<li>Data Export Console - Improvements to parameter validation. Especially cases where the wrong number of parameters are provided.</li>
<li>Option to collapse/expand the log selection with the log viewer.</li>
<li>MetadataServiceWrapper: deploy aura components in packages.</li>
</ul>
<h2>Other changes 3.7.17251.2</h2>
<ul>
<li>FitDx: --filter option for user defined events. --summary option for count by event type.</li>
<li>Add optional allowExistingSObjectsWithoutId="true" to the binding configuration element to allow sObjects to be created with a null Id. Typically this isn't allowed as the ID is used to control insert/update operations and to identify relationship types. This setting can be used for more basic SOQL queries where the results won't be subsequently used for DML.</li>
</ul>
FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-71874908113875719992018-06-27T08:35:00.004+12:002020-03-02T07:25:25.281+13:00Speeding up Salesforce unit testing performance<div class="separator" style="clear: both; text-align: center;"><a href="https://salesforce.stackexchange.com/a/3697/102" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://i.stack.imgur.com/tmikt.png" width="400" height="349" data-original-width="413" data-original-height="360" /></a></div>
<p>For many years I've had this thorn in my side with Apex test cases. It goes by the name of "Disable Parallel Apex Testing" and since Spring `13 (v27.0) it has needed to be enabled constantly else I'd get a <a href="https://salesforce.stackexchange.com/a/8518/102">UNABLE_TO_LOCK_ROW error</a> due to the custom hierarchy settings that get updated in the test cases.</p>
<p>Leap forward to Summer/Winter `18 (v42.0/v43.0) and I'm still tangling with this. That's <a href="https://xkcd.com/1205/">five years of waiting</a> for all the test classes to run sequentially one after another. That's about the right amount of procrastination to finally fix this problem! So hold on, were going to raise a support case and keep at this until the bitter end<sup><a href="#foot1">1</a></sup>.</p>
<p><i>What follows is a true story. The namespaces and class names have been changed to protect the innocent, but the snippets of messages with support are real.</i></p>
<h2 style="clear: both;">Step 1 - Turning off "Disable Parallel Apex Testing"</h2>
<p>This was simple enough. Uncheck a checkbox, run all the tests, and... Uh oh.</p>
<blockquote><a href="https://salesforce.stackexchange.com/q/217551/102">Could not run tests on class 01p400000000001 because: connection was cancelled here</a></blockquote>
<p>With that setting checked all my tests were passing. Now some of my previously passing test classes are falling over when run in parallel. Worse still, the specific test classes to fail were intermittent. It wasn't just one specific class causing a problem. Any one of a dozen or so classes could fail in this manner and they would change from run to run.</p>
<h2 id="isParallel" name="isParallel">Step 2 - Winter `18 @isTest isParallel annotation to the rescue</h2>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhI9wlMMMUqRtYvw_yK-zfYw5pKaONLSaYZZJklCVG4zzy-2PqqnVPxN7GTDvlb-uugMtI-6xjC155NJ72JclntnTYlD90TaXghBZsT8FxvRxvGrmItO0q8LrdPQw3CSf29s7GhGr3akqyu/s1600/the-istestisparallelfalse-attributes-they-do-nothing.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhI9wlMMMUqRtYvw_yK-zfYw5pKaONLSaYZZJklCVG4zzy-2PqqnVPxN7GTDvlb-uugMtI-6xjC155NJ72JclntnTYlD90TaXghBZsT8FxvRxvGrmItO0q8LrdPQw3CSf29s7GhGr3akqyu/s400/the-istestisparallelfalse-attributes-they-do-nothing.jpg" width="400" height="300" data-original-width="500" data-original-height="375" /></a></div>
<p><a href="https://releasenotes.docs.salesforce.com/en-us/winter18/release-notes/rn_apex_annotation_istest_isparallel.htm">Winter 18</a> added the new <code>@isTest(isParallel=true)</code> annotation to:</p>
<blockquote>indicate test classes that can run in parallel and aren’t restricted by the default limits on the number of concurrent tests.</blockquote>
<p>That's great, except I don't want to modify 90% of my test classes to deal with the 10% that are having issues. No, I'll just use <code>@isTest(isParallel=false)</code> and explicitly exclude the problem cases... except that doesn't work. At least not at the time of writing. Please vote for the idea <a href="https://success.salesforce.com/ideaView?id=0873A0000003VhKQAU">Parallel Tests Option (isParallel) on the @IsTest Annotation to exclude tests</a> to make this a viable approach.</p>
<h2 style="clear: both;">Step 3 - Once more unto the support case, dear friends, once more</h2>
<p><span class="supportDay">[Day 1 - 2018-05-09]</span> Desperate times. Let's raise a support case to see if they can isolate the underlying issue.</p>
<p><span class="supportDay">[Day 6 - 2018-05-14]</span> After a bit of back and forth with tier 2 to establish how to reproduce the problem (press the run all test cases in the org) the initial advice back was:</p>
<blockquote class="supportResponse">
The root cause of this issue?<br/>
Answer: - Parallel test execution is the root cause of this issue. <br/>
<br/>
Solution?<br/>
Answer: - Disable Parallel test execution. <br/>
<br/>
Question: - Why do you need to Disable Parallel Apex Testing? <br/>
Answer: - As per the salesforce document, Tests that are started from the Salesforce user interface (including the Developer Console) run in parallel. Parallel test execution can speed up test run time. Sometimes, parallel test execution results in data contention issues, and you can turn off parallel execution in those cases.
</blockquote>
<p>Huh. Well, yes I knew that already (as per the case description when I raised it). That would work, but it's been five years of this situation, so lets push a bit harder. <a href="https://www.xkcd.com/806/">SHIBBOLEET!</a></p>
<h2>Step 4 - How bad is the problem empirically?</h2>
<p>Before responding with a kiwi <a href="https://youtu.be/xWsQ5lwgpSw?t=3m1s">yeah-nah</a> to support I timed the total test run time for both parallel and synchronous test execution:</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Synchronous test run is ~12% slower, but I could easily lose that time needing to watch for the parallel failures and rerun them.</p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/996535323558473729?ref_src=twsrc%5Etfw">May 15, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>As it stood, the parallel test execution was marginally faster as long as I reran any initially failed test cases immediately after the first run completed. That was an interesting result, and I think I can explain the similar timing between the two <a href="#reason">later on</a>.</p>
<p>The <a href="https://twitter.com/FishOfPrey/status/996542962514382848">general consensus on twitter</a> was that updates to custom hierarchy settings were probably to blame for the contention and subsequent timeouts.</p>
<h2>Step 5 - Isolating Custom Hierarchy Settings using the Stubbing API</h2>
<p>I use a number of hierarchy custom settings to toggle various functions in the app. All interactions with those settings from Apex are done via a single class. This allows for sensible defaults etc...</p>
<p><i>Those with particular feelings on how mock testing should be performed or a sensitive testing disposition may want to look away now...</i></p>
<p>To prevent any potentially blocking DML operations on the custom hierarchy settings I've injected a <a href="https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_interface_System_StubProvider.htm">StubProvider</a> when in a testing context. The StubProvider prevents any DML occuring when altering the settings in Apex tests. This isn't the typical usage for a test mocking framework, but it serves my needs here to help avoid database locking issues.</p>
<p>Here is a shortened version of how it looks:</p>
<style type="text/css">
.gist-file
.gist-data {max-height: 400px;}
span.supportDay {color: #227777;}
pre.supportResponse { white-space: pre-wrap; background-color: #112222;}
blockquote.supportResponse { border-left-width: 6px; border-left-color: #112222; border-left-style: double; padding-left: 2px; }
pre.toSupport { border-left-width: 6px; border-left-color: #222211; border-left-style: double; }
</style>
<!--FishOfPreySettings-->
<script src="https://gist.github.com/FishOfPrey/9ef39b32948f23b604c8e8e0ab041c53.js"></script>
<!--FishOfPreySettingsMockProvider-->
<script src="https://gist.github.com/FishOfPrey/fdf33076e404ebc878b683f6383c67fc.js"></script>
<!--FishOfPreySettings_Test-->
<script src="https://gist.github.com/FishOfPrey/23ebd116f84b520b0db57e3c489a6c60.js"></script>
<p>And after all that the result on the asynchronous test execution was..... not much really. The tests were marginally faster, but the underlying problem with the test classes having the connection closed remains. At least I can rule out DML on the custom settings as being the problem.</p>
<h2>Step 6 - Back to the drawing board</h2>
<p>Blaming the problem on the custom hierarchy settings made sense from a historical perspective, but it doesn't appear to be the source of my challenges.</p>
<p>I went back and had a closer look at the debug logs from the tests in the run. That's when I saw it:</p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjS3gfSXThMM0KjoHiNg9jOa8XPCEsJNxiA6MUGG8cGJ8duxmppfbrG06kqLr_WmGF1Dzpk5rQKVMLYgeRyy0LM3Uw6z-zQB04Judvz5wjb5K9f5Mg2U21A8ReV4Lq8so0pyJnPGlfzhFP_/s1600/Timelines.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjS3gfSXThMM0KjoHiNg9jOa8XPCEsJNxiA6MUGG8cGJ8duxmppfbrG06kqLr_WmGF1Dzpk5rQKVMLYgeRyy0LM3Uw6z-zQB04Judvz5wjb5K9f5Mg2U21A8ReV4Lq8so0pyJnPGlfzhFP_/s800/Timelines.png" width="760" data-original-width="896" data-original-height="388" /></a>
<p><b>"What?"</b>, you may ask, <b>"Am I currently looking at?"</b></p>
<p>That colorful image is a selection of debug log timelines from various parallel test runs. Ignoring the majority of the markings, the important thing is a <span style="color: #DA70D6">purple line representing a DML operation</span> that is taking more and more of each transaction. Right up until the point that Salesforce starts terminating it. If we drill into one of those logs we can see it is a DML operation to insert 6 records taking 3 minutes 52 seconds (for 6 records!):</p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyTwIJmtszUP36YnyvHDnqDcy7luueTykn5flYxRTiLISo3P7X2zZ1MHQZtVLXPxa-A7CuNnTGBmo0rKFpX_hN5gNgkRFqzt8OGVKm1Lmi-LQAzBLwKWirQzeZwDbbICRLS_Ey-yxyPGKl/s1600/LogEventZoom.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyTwIJmtszUP36YnyvHDnqDcy7luueTykn5flYxRTiLISo3P7X2zZ1MHQZtVLXPxa-A7CuNnTGBmo0rKFpX_hN5gNgkRFqzt8OGVKm1Lmi-LQAzBLwKWirQzeZwDbbICRLS_Ey-yxyPGKl/s800/LogEventZoom.png" width="760" data-original-width="1009" data-original-height="135" /></a>
<pre style="white-space: pre-wrap;">
14:14:15.0 (325578801)|DML_BEGIN|[992]|Op:Insert|Type:DFB__OpportunityPriceType__c|Rows:6
14:18:07.376 (232376043557)|DML_END|[992]
</pre>
<h2>Step 7 - Returning to the support case with proof</h2>
<p><span class="supportDay">[Day 9 - 2018-05-17]</span> If that isn't a smoking gun then I don't know what is. Let's take this new evidence back to the support case. </p>
<p>Me to support:</p>
<blockquote class="toSupport">
I've just noticed something else odd in the debug logs for the running tests. Inserts to DFB__OpportunityPriceType__c for 6 rows are taking an excessive amount of time. <br/>
<br/>
I'm seeing times for the CommonTestSetup.createPriceTypeMappings() method of between 20 and 45 seconds to complete. <br/>
Attached Log1.txt - Look for the lines:<br/>
16:18:58.0 (150146460)|DML_BEGIN|[941]|Op:Insert|Type:DFB__OpportunityPriceType__c|Rows:6<br/>
16:19:19.214 (21214892238)|DML_END|[941]<br/>
<br/>
It isn't clear to me why the inserts for those records are taking so long. The fields on it are [reasonably] basic and it is only 6 rows. <br/>
The only thing I can think of is that all the test classes are trying to use the same records and they all have the same indexed values in the PriceTypeID__c field.
</blockquote>
<p>A bit more context as you dear reader can't see into the org like support can.</p>
<p>I have a custom object <code>DFB__OpportunityPriceType__c</code> with a unique external id field. That field is indexed. Just about every single test class I have requires data in this custom object as it contains configuration that gets linked to from Opportunity records. I thought I was being clever and used a <code>@TestSetup</code> method to insert 6 of these records once for all the other test methods to use. There are no triggers, workflow outbound messages or other automatons hanging off this custom object. None of the test classes use <code>SeeAllData=true</code>.</p>
<h2>Step 8 - More steps in the Support dance</h2>
<p><span class="supportDay">[Day 13 - 2018-05-21]</span> Support responds:</p>
<blockquote class="supportResponse">I reviewed your case and ran the test classes to troubleshoot the issue further. I noticed the error in the server log "RunningForTooLongException: connection was canceled here".<br/>
The error is thrown because - for asynchronous Apex tests, any test method execution has a timeout limit. Once an Apex test run exceeds 6 minutes, an internal process "kills" it. <br/>
<br/>
After reviewing the logs, it seems that this particular method is taking time to execute when all the tests classes are run asynchronously -
CommonTestSetup.minimalSetupWithSettings();<br/>
<br/>
Can you please try to refactor this method and see if it can be optimized?<br/>
I see there are many methods being called from this function. </blockquote>
<p>Another frustrating response. They pointed out the method that gets called directly in the <code>@testSetup</code> method. I'd already identified the inner method from that one and even the line in question. That it is a RunningForTooLongException is new information, but I'm no closer to what is blocking those records from inserting.</p>
<p><span class="supportDay">[Day 15 - 2018-05-23]</span> We try a GoToMeeting. I work through with Tier 2 support in ensuring the external ID's that get assigned to DFB__OpportunityPriceType__c records in the test cases are unique per <code>@testSetup</code>. It didn't seem to help. Beyond that, I think support has a good grasp of the problem now.</p>
<p><span class="supportDay">[Day 20 - 2018-05-28]</span> The support case has been escalated to Tier 3.</p>
<p><span class="supportDay">[Day 30 - 2018-06-07]</span> Tier 3 responds:</p>
<blockquote class="supportResponse">
- When 'Disable Parallel Apex Testing' checkbox is checked in Developer Console. <br/>
Result: Running Perfect <br/>
<br/>
- When 'Disable Parallel Apex Testing' checkbox is unchecked in Developer Console. <br/>
Result: Exception is thrown <br/>
<br/>
- In Serial Mode, it's working perfectly because it's running in Sync mode and no data contention issue. <br/>
However, in Parallel mode, multiple classes and trigger have been invoked in the same context/transaction where performing DML Operation and also making callouts and waiting for a response in Async mode. This may cause some data contention. Also since there is a lot of custom code involved it becomes very difficult for us to analyze the scenario. <br/>
<br/>
- This is WAD as per Salesforce documentation. If Apex Class will take more than 6 minutes of time to complete the transaction, the connection will be closed by Salesforce DB. <br/>
<br/>
- Test classes are run in serial mode during deployment. This error will not occur when you are trying to deploy your package. <br/>
<br/>
Possible workarounds - <br/>
<br/>
- Try to modify the code and remove that many dependencies.<br/>
- Else run in Serial Mode as a Workaround.
</blockquote>
<p>This seems distinctly like they put it in the too hard basket and are trying to avoid investigating the actual issue. I'll push back to see if I can get a better answer.</p>
<p>Also, I'm not sure what they mean by "making callouts and waiting for a response in Async mode". This is all happening in a test context. There are no callouts or waiting for async responses. I'm not going to pursue that as I don't want to get distracted.</p>
<p><span class="supportDay">[Day 35 - 2018-06-12]</span> Update from support.</p>
<blockquote class="supportResponse">My T3 has officially logged an investigation with our RnD team on this issue. My RnD team is currently reviewing the case. </blockquote>
<p><span class="supportDay">[Day 36 - 2018-06-13]</span> An update from R&D, as communicated via Tier 2.</p>
<blockquote class="supportResponse">
I have received an update from the DB team on this case. <br/>
<br/>
As per the DB team, it seems that the parallel sessions are working on common recordsets and causing the wait events. <br/>
Because of this waitime <u title="Huh - What?">the DB team is high</u> and eventually the classes are getting timed out. <br/>
<br/>
May be this explains why the insertion to DFB__OpportunityPriceType__c is taking time. We cannot exactly comment on the common recordsets but DFB__OpportunityPriceType__c records is one of the potential candidate. <br/>
<br/>
Solution - <br/>
Have the parallel sessions work on different recordset/dependencies to avoid this situation.
</blockquote>
<p>So it appears that all the test cases are trying to work with the same record sets and they are all blocking until they can get exclusive access to those records. They either stack up and run one after another or wait so long they time out. This <a name="reason" id="reason">explains</a> why the parallel test performance is so similar to the serial performance.</p>
<p>I'm fairly certain the <code>DFB__OpportunityPriceType__c</code> records are unique between <code>@testSteup</code> executions, so it must be something else...</p>
<h2>Step 9 - Time to regroup</h2>
<p><span class="supportDay">[Day 42 - 2018-06-19]</span> Much to my shame I've closed the case out. I need time to regroup and revisit this from a new approach. I'm certainly not giving up on it yet and have a few ideas to try:</p>
<ul>
<li>Try adjusting the Logging levels used when capturing the logs. Particularly around the Database logging levels. Also try capturing no logs at all.</li>
<li>Push the entire packages metadata into a Scratch Org and and retry the tests. The dev org doesn't have much data loaded, but the scratch org can provide a completely empty environment to ensure it isn't a data siloing issue.</li>
<li>If it is reproducable in the scratch org, start hacking parts out until it becomes easier to reproduce.</li>
<li>Remove the creation of the DFB__OpportunityPriceType__c records from the @testSetup. Only create them when required in the individual test methods.</li>
<li>Simplify the test cases where possible. The challenge is almost all of them work with Opportunities and OpportunityLineItems at some level. Which means a large overhead to construct all the dependent records as well.</li>
</ul>
<hr/>
<h2>Footnotes</h2>
<ol>
<li name="foot1" id="foot1">The <i>bitter end</i> may or may not occur within the timeframe of this blog post.</li>
</ol>
<!--I was tempted to open with a click bait type title: How I quadruppled my test throughput with this one simple trick-->FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-11271973889490637922018-05-16T09:31:00.000+12:002018-05-16T09:31:03.920+12:00Fiddling with the SFDX CLI API calls<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEja5zbUs5rHeC60lbO2Og3xGiBLC4h5kXaQ4xjeUnYKI-4KmPb8HaUEitFWbP0pyj2nSuqaYEJ7XUsYaIOjuz-0Vrt4fcB-CnPTv3AP2mS0o20GNVODHIaud5CcCXdEVVmclmUUu4FiZzzd/s1600/MakesItTick_sml.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEja5zbUs5rHeC60lbO2Og3xGiBLC4h5kXaQ4xjeUnYKI-4KmPb8HaUEitFWbP0pyj2nSuqaYEJ7XUsYaIOjuz-0Vrt4fcB-CnPTv3AP2mS0o20GNVODHIaud5CcCXdEVVmclmUUu4FiZzzd/s320/MakesItTick_sml.png" width="320" height="320" data-original-width="601" data-original-height="601" /></a></div>
<p>What makes the <code>sfdx</code> CLI tick? Sometimes learning how something works can be as much fun as actually using it.</p>
<p>The goal here is to capture the raw API calls the <code>sfdx</code> CLI is sending to the Salesforce APIs. In addition to a better understanding of what it is doing you can use it to debug the CLI itself.</p>
<p>This post was inspired by a, ahem, very similar post by Christian Carter - <a href="http://cdcarter.github.io/sfdx/2018/05/22/charles-proxy-sfdx">SFDX With Charles Proxy</a>. The primary difference is that I'm using <a href="https://www.telerik.com/fiddler">Fiddler</a> on Windows rather than Charles Proxy on macOS.</p>
<p>Using the <a href="https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_cli_log_messages.htm">direct sfdx logging support</a> is another option to monitor what is going on. Or even browsing the source directly under <code>%LOCALAPPDATA%\sfdx</code> (seems they are going to some lengths to hide the source now). While something like fiddler is more complicated (some might even say "fiddly") to configure, it is harder to hide anything from it (intentionally or otherwise).</p>
<h2 style="clear: both;">Configure to intercept HTTPS traffic</h2>
<p>After installation the first this is to configure Fiddler and Windows to allow interception and decryption of HTTPS traffic.</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGag0skRcPeJE05qg_vs3xHPriWn2G2mJBSuYlZrW7ZHfds8Sov-_g0dtXq1FM479rVxhZ7biNc19DEM5_aogkVVzeAg3pOr5K9CYJq72p2ugJ1FMzWNnmj4_T_6K3o_WiEPQl4zb2boMW/s1600/ScaryText.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGag0skRcPeJE05qg_vs3xHPriWn2G2mJBSuYlZrW7ZHfds8Sov-_g0dtXq1FM479rVxhZ7biNc19DEM5_aogkVVzeAg3pOr5K9CYJq72p2ugJ1FMzWNnmj4_T_6K3o_WiEPQl4zb2boMW/s1600/ScaryText.png" data-original-width="549" data-original-height="377" /></a></div>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtE8GYimEADQ7yOSfcHxgF2ty97KcvrMjY8P5Y8IYneUkGVEBK5F5wZvyM5iAGYd-oo39w4J5JmmWyo4NFiAWE_o9wt_mVbzeWt7DRG3HL3HdAlKAH1BVSUx88wPPUnGrJD4nos5lCbZO2/s1600/PerformDecryption.PNG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtE8GYimEADQ7yOSfcHxgF2ty97KcvrMjY8P5Y8IYneUkGVEBK5F5wZvyM5iAGYd-oo39w4J5JmmWyo4NFiAWE_o9wt_mVbzeWt7DRG3HL3HdAlKAH1BVSUx88wPPUnGrJD4nos5lCbZO2/s1600/PerformDecryption.PNG" data-original-width="513" data-original-height="89" /></a></div>
<ol>
<li>Tools > Options</li>
<li>HTTPS tab</li>
<li>Check <b>Decrypt HTTPS traffic</b></li>
<li>Click 'Yes' to reconfigure Windows' Trusted CA Certificate
<b>You might want to <a href="https://en.wikipedia.org/wiki/Root_certificate">read up</a> on what a Root Certificate is before doing so.</b></li>
<li>(Optional) change the drop down from "... from all processes" to "... from non-browsers only"</li>
<li>(Optional) Toggle the "Skip decryption for the following hosts" to "Perform decryption for the following hosts". Then add *.salesforce.com</li>
</ol>
<p style="clear: both;">Now the Fiddler is ready to intercept the traffic you need to configure <code>sfdx</code> to send it to the correct location. The default proxy port of 8888 is configured under <i>Options > Connections > Fiddler listens on port:...</i> </p>
<pre>
set http_proxy=http://localhost:8888
set https_proxy=https://localhost:8888
</pre>
<p>If you just stop there and try and call <code>sfdx force:org:list</code> you will find the CONNECTED STATUS comes back as "ECONNRESET". It would appear that node.js doesn't like our self signed root certificate. You can tell node to mind its own <!--damn--> business with:</p>
<pre>
set NODE_TLS_REJECT_UNAUTHORIZED=0
</pre>
<p>Again, you only want to do this for a single session and not configure that across all processes. It potentially opens you up to all sorts of man in the middle security attacks.</p>
<h2>Now what?</h2>
<p>Now my friend, now we can see each and every callout to the Salesforce APIs and the corresponding responses.</p>
<p>Lets look at what happens with the command <code>sfdx force:org:list</code>.</p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU5tWEvKVjaB0JoZdAGVxVv_HUE22mbTthjV2UlRKZFqlHWHD59_6AP3TGMkJapd3f01EZS-CGP6YAFY4cUerEuY43qNaxSc8DbEfYPLY3_ZbL5mb1jfupiwu8nMn2dtaETkEcHuYLi35x/s1600/forceOrgList.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU5tWEvKVjaB0JoZdAGVxVv_HUE22mbTthjV2UlRKZFqlHWHD59_6AP3TGMkJapd3f01EZS-CGP6YAFY4cUerEuY43qNaxSc8DbEfYPLY3_ZbL5mb1jfupiwu8nMn2dtaETkEcHuYLi35x/s1600/forceOrgList.png" data-original-width="783" data-original-height="122" width="755" /></a>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg256bng9AvWhMEUvG95AkZm78jv1MEFIxH2_0oEZUBQQlIuRmpStvnvpZFgKxWM86rXN1omN1H12z-oVdaD4KN-i6c3J8L3-QI_5vJiAgv01bX4RbSq0CYdr4GGCqH5RM8pMP1qUoQmMWe/s1600/FiddlerOutput.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg256bng9AvWhMEUvG95AkZm78jv1MEFIxH2_0oEZUBQQlIuRmpStvnvpZFgKxWM86rXN1omN1H12z-oVdaD4KN-i6c3J8L3-QI_5vJiAgv01bX4RbSq0CYdr4GGCqH5RM8pMP1qUoQmMWe/s1600/FiddlerOutput.png" data-original-width="905" data-original-height="302" width="755" /></a>
<p>This reveals up to four API calls per valid Org. The exact calls will depend on the org types and if you have recently successfully authenticated to them. Generally, you get:</p>
<ol>
<li>A failed <b>GET /services/data/v42.0</b> with an invalid token</li>
<li>A <b>POST /services/oauth2/token</b> to refresh the access token</li>
<li>A successful <b>GET /services/data/v42.0</b></li>
<li>A <b>GET /services/data/v42.0/query?q=...</b> with a SOQL query over ScratchOrgInfo. Presumably this only works with Scratch Orgs at this time.</li>
</ol>
<p>So every org you register with SFDX needs 3 or 4 API calls with a force:org:list. There is certainly something to be said for dropping unused orgs.</p>
<p>Anyway... Happy Fiddling!</p>FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-73790652061415084052018-05-09T12:28:00.000+12:002018-05-30T10:18:52.745+12:00Salesforce Log Categories and Events by Level - Revisited<p>Way back in June 2014 I posted a table to logging events by level and category - <a href="http://www.fishofprey.com/2014/06/salesforce-log-categories-and-events-by.html">Salesforce Log Categories and Events by Level.</a></p>
<p>I was never really happy with the table layout trying to squeeze that much data in. Also, new logging levels keep getting added and several have been shuffled around recently with respect to the level they occur at.</p>
<p>Here is a hopefully simpler revised attempt using lists. It is compiled directly from the Debug Log Levels detail page, so it should be eaiser to keep up to date.</p>
<p>Similar data can be found in the <a href="https://help.salesforce.com/articleView?id=code_setting_debug_log_levels.htm#DebugEventTypesSect">Debug Log Levels documentation</a>. I found at the time of publishing that I had several in my list that didn't appear on that page, such as CALLOUT_REQUEST_PREPARE, USER_DEBUG_WARN, and DUPLICATE_DETECTION_MATCH_INVOCATION_DETAILS.</p>
<p>The levels are cumulative. So everything that appears at the ERROR level will appear at all the lower levels as well. Everything at the WARN level will appear at INFO, DEBUG, FINE, ... and so on.</p>
<style>
.gist { color: inherit !important;}
.gist-data {background-color:inherit !important;}
</style>
<script src="https://gist.github.com/FishOfPrey/9c6b6d3a6d9e0147143b0c54d615a677.js"></script>
<ul>
<li>Updated for <a href="https://gist.github.com/FishOfPrey/9c6b6d3a6d9e0147143b0c54d615a677/revisions#diff-8a48cbc688e7dc15b4808c2343ae0092">Summer '18 - v43.0</a></li>
</ul>FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-62882549519199898232018-04-10T12:06:00.000+12:002018-04-20T10:57:25.957+12:00The unofficial way to install Apps and Packages in Your Trailhead Playground <div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZ-Kq2HkAA5N9XOgRZMIGOOSh5-LHWoMD60t2CNS2gceJ8Vas-KWGIFbEk8BaBwEMq3D8zlv9kxDcjfLM2ft8G5UkvkUdCqOX4Cg0VLUQ40IiHVbCbcCGtfvQKNV3XReP0K-C92OxXgwio/s1600/DeploymentFishApproved.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZ-Kq2HkAA5N9XOgRZMIGOOSh5-LHWoMD60t2CNS2gceJ8Vas-KWGIFbEk8BaBwEMq3D8zlv9kxDcjfLM2ft8G5UkvkUdCqOX4Cg0VLUQ40IiHVbCbcCGtfvQKNV3XReP0K-C92OxXgwio/s1600/DeploymentFishApproved.png" data-original-width="200" data-original-height="200" /></a></div>
<p>There is a Trailhead module called <a href="https://trailhead.salesforce.com/modules/trailhead_playground_management">Trailhead Playground Management</a> that includes a unit on <a href="https://trailhead.salesforce.com/modules/trailhead_playground_management/units/install-apps-and-packages-in-your-trailhead-playground">Install[ing] Apps and Packages in Your Trailhead Playground</a>. This is an important step in many other modules and day to day Salesforce work. You need to be able to install an App/Package into a target org so you can use its features.</p>
<p>The unit goes into the steps in some detail and focuses on being accessible to those just starting out with Salesforce.</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgORFjpsiW6E2SIQpsqZP6qUgeDYIKm6sVaeGvhCprRurAB8ocD2s307qKtL5N_bcNVUyFwRtXmT9i0MS5KVnaj2Q_QJdoTNwKSrr-dm5QdDjFfzk_bnigBZlN__GmKRXXTM3AX82JZKjOL/s1600/InstallManagedPackage.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgORFjpsiW6E2SIQpsqZP6qUgeDYIKm6sVaeGvhCprRurAB8ocD2s307qKtL5N_bcNVUyFwRtXmT9i0MS5KVnaj2Q_QJdoTNwKSrr-dm5QdDjFfzk_bnigBZlN__GmKRXXTM3AX82JZKjOL/s1600/InstallManagedPackage.PNG" width="700" data-original-width="902" data-original-height="390" /></a></div>
<p>Above is a quiz question from the <a href="https://trailhead.salesforce.com/modules/trailhead_playground_management/units/get-your-trailhead-playground-username-and-password">Trailhead Playground Management</a> module. It's technically correct as per the instructions in that module, but I don't think it is the best approach and from what I've seen is a common source of confusion.</p>
<p>I'd like to present an alternative approach. It might not be as accessible, but it does bypass a number of steps that can lead to further complications. So, without any more fanfare I present the Deployment Fish approved way of installing packages and apps into a Salesforce Org.</p>
<h2>The URL <strike>Hack</strike> Manipulation Maneuver</h2>
<p>The steps are as follows:</p>
<ol>
<li>Obtain the package installation URL.</li>
<li>Copy everything from that URL except for the domain</li>
<li>Log into the org where you want to install the package</li>
<li>Paste the content copied from Step 2 after the domain.</li>
<li>Follow the remaining prompts.</li>
</ol>
<p>Let us try this as a worked example using the <a href="https://login.salesforce.com/packaging/installPackage.apexp?p0=04tB00000009UeX">Install the DreamHouse app package</a> from the Trailhead unit</p>
<ol>
<li>Obtain the package installation URL:<br/>Just right click on the package link and Copy Link Address. The approach will vary based on the browser, but there should be a fairly simple way to extract the link.<br/>https://login.salesforce.com/packaging/installPackage.apexp?p0=04tB00000009UeX</li>
<li>Copy everything from that URL except for the domain:<br/><b>/packaging/installPackage.apexp?p0=04tB00000009UeX</b><br/>The ID with the <a href="http://www.fishofprey.com/2011/09/obscure-salesforce-object-key-prefixes.html#04t">04t keyprefix</a> is the important part here. That identifies what package/app you are installing.</li>
<li>Log into the org/playground where you want to install the package<br/><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPyoHHhkitEttdmdMxiuXJ1CnNhErMdGpwNa3kmo-kayEDCxxbaz_AKvVoUztURdA6liC13v-ofk1Ke8y8ylAuzcyaLsY2sp0KjcZ5whxHnL-CAIc10uWPhuUex7d-oD4QL-3uoQ_3mzv4/s1600/LaunchPlaygrount.gif" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPyoHHhkitEttdmdMxiuXJ1CnNhErMdGpwNa3kmo-kayEDCxxbaz_AKvVoUztURdA6liC13v-ofk1Ke8y8ylAuzcyaLsY2sp0KjcZ5whxHnL-CAIc10uWPhuUex7d-oD4QL-3uoQ_3mzv4/s1600/LaunchPlaygrount.gif" data-original-width="561" data-original-height="301" /></a></li>
<li id="step4">Paste the content copied from Step 2 after the domain.<br/>
<b>URL before:</b> <b>https://curious-raccoon-286917-dev-ed.lightning.force.com</b>/one/one.app#/home<br/>
<b>URL after:</b> <b>https://curious-raccoon-286917-dev-ed.lightning.force.com</b><u>/packaging/installPackage.apexp?p0=04tB00000009UeX</u><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5uAj-5cISLBAJJOhnjySTtA66yr2O7yts8i3A1xhNp7ZgPaxVaIyxopyTT4mjYtInduOie5ZU2QoEFOWDwR0THKIGGYcJ0iLBDFGvUkCEcawlwOerLGQ4yupOQnbijQWOh88tw3aoF5AI/s1600/PackageURL.gif" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5uAj-5cISLBAJJOhnjySTtA66yr2O7yts8i3A1xhNp7ZgPaxVaIyxopyTT4mjYtInduOie5ZU2QoEFOWDwR0THKIGGYcJ0iLBDFGvUkCEcawlwOerLGQ4yupOQnbijQWOh88tw3aoF5AI/s1600/PackageURL.gif" data-original-width="720" data-original-height="301" width="720" /></a></li>
<li>Follow the remaining prompts.</li>
</ol>
<h2>AppExchange packages</h2>
<p>A similar technique can be used with the AppExchange. The only catch here is they make it a bit harder to get the package version id. Lets use the <a href="https://appexchange.salesforce.com/appxListingDetail?listingId=a0N30000004gHhLEAU">Salesforce Adoption Dashboards</a> as an example app.</p>
<ol>
<li>From the <a href="https://appexchange.salesforce.com/appxListingDetail?listingId=a0N30000004gHhLEAU">app listing</a>, press "Get It Now".</li>
<li>You may need to login to the AppExchange. It doesn't matter what account you log in with at this step.</li>
<li>On the "Where do you want to install this package?" select either the "Install in Production" or "Install in Sandbox" buttons. It shouldn't matter.
</li>
<li>Move past the Confirm Installation Details page and press "Confirm and Install"</li>
<li>You will end up at a login page. <b>DO NOT LOGIN HERE!</b><br/>Look closely at the URL. You will see the package version ID.<br/>
In my case it was https://login.salesforce.com/?startURL=%2Fpackaging%2FinstallPackage.apexp%3Fp0%3D<u><b>04t410000009jsfAAA</b></u>%26newUI%3D1%26src%3Du
<br/><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKGDF1l-bryHkI4j4aYo1g_3Jlx6pvl1C-Mmp4MqKEEzJxveH2MpWM2sMF6xLabyQUvWzIj8iqGCSQGSuOEHlo-IsBikGEt1xj-MmjSfl4850lbnIBBA9t3LIdiz427Wj1Yx5kJMNQGJY6/s1600/PackageVersionId.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKGDF1l-bryHkI4j4aYo1g_3Jlx6pvl1C-Mmp4MqKEEzJxveH2MpWM2sMF6xLabyQUvWzIj8iqGCSQGSuOEHlo-IsBikGEt1xj-MmjSfl4850lbnIBBA9t3LIdiz427Wj1Yx5kJMNQGJY6/s1600/PackageVersionId.png" data-original-width="1048" data-original-height="95" width=720 /></a></li>
<li>Append that ID to /packaging/installPackage.apexp?p0= on your actual target org as you did in <a href="#step4">step 4</a> of the URL Manipulation Maneuver.<br/>/packaging/installPackage.apexp?p0=04t410000009jsfAAA</li>
</ol>
<hr/>
<p>These steps may look complicated at first, but in reality it is a small cut-and-paste job to find the package version Id. Once you have the Id the rest of the process becomes much simpler. You could even look at <a href="https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_dev2gp_install_pkg_cli.htm">automating the process using the SalesforceDX CLI</a>.</p>
<p>The real benefit is for those that routinely work between multiple orgs. It provides more certainty that you are installing in the org you intended to. Plus you don't even need to figure out your Trailhead playgrounds authentication details.</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">¯\_(ツ)_/¯<br>When you jump between multiple orgs all day directly changing the URL often seems like the easiest way to target the correct org. Way to often the auth process sends me into an unexpected org.</p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/983468022554812416?ref_src=twsrc%5Etfw">April 9, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-16318487462332766752018-04-01T21:59:00.000+12:002018-04-01T21:59:52.008+12:00Breeding your own deployment fish<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLHRAzecmIwEft1Jz2Ai7NTwlb8ZG_NXwc78tQm9mN9csVxhiMhP_najuXktR5xTIjNzAhFIanqXvgnFYDbTjsl9L1BFiVjySo5zsKdooQGhESuH5Eqo3txY3g_1K5yoC4auscGsHTtPzZ/s1600/DXjEuE_VQAAg6yM.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLHRAzecmIwEft1Jz2Ai7NTwlb8ZG_NXwc78tQm9mN9csVxhiMhP_najuXktR5xTIjNzAhFIanqXvgnFYDbTjsl9L1BFiVjySo5zsKdooQGhESuH5Eqo3txY3g_1K5yoC4auscGsHTtPzZ/s320/DXjEuE_VQAAg6yM.jpg" width="320" height="296" data-original-width="1600" data-original-height="1480" /></a></div>
<p>Sometimes it just isn't practical to head out into the ocean to catch your own deployment fish. Or the metadata gods don't favor your change set with a fresh catch.</p>
<p>What are you to do if the deployment fish aren't biting?</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">That is quite improper... good luck!<br>Is there a guide to making <a href="https://twitter.com/hashtag/deploymentfish?src=hash&ref_src=twsrc%5Etfw">#deploymentfish</a> ? <a href="https://twitter.com/deploymentfish?ref_src=twsrc%5Etfw">@deploymentfish</a></p>— NA8 Pepper (@SForceBeWithYou) <a href="https://twitter.com/SForceBeWithYou/status/980166121432084480?ref_src=twsrc%5Etfw">March 31, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>JavaScript to the rescue!</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Experimenting with <a href="https://twitter.com/deploymentfish?ref_src=twsrc%5Etfw">@deploymentfish</a> anatomy. Too much Tail? <a href="https://t.co/VNp0imQ4I7">pic.twitter.com/VNp0imQ4I7</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/800484684165574656?ref_src=twsrc%5Etfw">November 20, 2016</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>A few moments of playing on the /changemgmt/monitorDeploymentsDetails.apexp page reveals that JSON data about the current deployment status flows through <code>SfdcApp.MonitorDeployment.InProgressComponent.refreshInProgressSection</code>. We can call the same function ourselves and manipulate the <code>totalComponentsCount</code> and <code>succeededComponentsCount</code> data as required:</p>
<p>
<code>
SfdcApp.MonitorDeployment.InProgressComponent.refreshInProgressSection(Sfdc.JSON.parse('{"hasErrors":false,"hasFatalError":false,"refreshInternalInMillis":3000,"hasCodeCoverageError":false,"totalTestsCount":20,"totalComponentsCount":4,"succeededComponentsCount":21,"isComponentSaveFailing":false,"isDeployComplete":true,"failedComponentsCount":0,"failedTestsCount":0,"isDeployCanceled":false,"completedDate":"4/1/2018 1:33 AM","hasTestRunStarted":false,"isCheckOnly":true,"isTestRunFailing":false,"isAbortRequested":false,"hasPayloadError":false,"isTestRunRequired":false,"stateDetail":"","succeededTestsCount":20,"deployStatus":"Succeeded"}'), !0);
</code>
</p>
<p>Better yet, we can wrap it in our own function to call as required.</p>
<pre>
function deploymentFish(a, b) {
var c = Sfdc.JSON.parse(document.getElementById(chartDataHiddenElementId).value);
c.succeededComponentsCount = a;
c.totalComponentsCount = b;
document.getElementById(chartDataHiddenElementId).value = Sfdc.JSON.stringify(c);
SfdcApp.MonitorDeployment.InProgressComponent.refreshInProgressSectionBasedOnServerData();
}
</pre>
<p>Or, if you prefer, in <a href="https://en.wikipedia.org/wiki/Bookmarklet">bookmarklet</a> form: (Installation link for <a href="javascript:(function(){
var d = prompt('Deployment fish size?', '17/14');
var a = parseInt(d.split('/')[0]);
var b = parseInt(d.split('/')[1]);
var c = Sfdc.JSON.parse(document.getElementById(chartDataHiddenElementId).value);
c.succeededComponentsCount = a;
c.totalComponentsCount = b;
document.getElementById(chartDataHiddenElementId).value = Sfdc.JSON.stringify(c);
SfdcApp.MonitorDeployment.InProgressComponent.refreshInProgressSectionBasedOnServerData();
})();">Deployment Fish</a>)</p>
<pre>
javascript:(function(){
var d = prompt('Deployment fish size?', '17/14');
var a = parseInt(d.split('/')[0]);
var b = parseInt(d.split('/')[1]);
var c = Sfdc.JSON.parse(document.getElementById(chartDataHiddenElementId).value);
c.succeededComponentsCount = a;
c.totalComponentsCount = b;
document.getElementById(chartDataHiddenElementId).value = Sfdc.JSON.stringify(c);
SfdcApp.MonitorDeployment.InProgressComponent.refreshInProgressSectionBasedOnServerData();
})();
</pre>
FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-30049511424790268692018-03-12T22:08:00.000+13:002018-03-23T22:10:37.824+13:00The Trailhead Electric Imp project<div class="separator" style="clear: both; text-align: center;"><a href="https://developer.salesforce.com/resource/images/trailhead/badges/projects/trailhead_project_build_an_iot_integration_with_electric_imp.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://developer.salesforce.com/resource/images/trailhead/badges/projects/trailhead_project_build_an_iot_integration_with_electric_imp.png" width="180" height="180" data-original-width="200" data-original-height="200" /></a></div>
<p>For some time now I've been meaning to complete the <a href="https://trailhead.salesforce.com/en/projects/workshop-electric-imp">Electric Imp Trailhead project</a>. Unfortunately there were a couple of things holding me back from completing it.</p>
<p>Firstly, I needed the physical <a href="https://store.electricimp.com/collections/featured-products/products/impexplorer-developer-kit-for-salesforce-trailhead?variant=31720746706">impExplorer Developer Kit hardware</a>.</p>
<p>The board itself is a pretty reasonable $25 USD. And then I got to the shipping options to New Zealand in the cart and it looked something like this: (circa 2017)</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu48TxagqOx-h22sjH34q86tVxex5jS96gN6l0Cj03HPMKElNdbD_Xwu0MwaYk_IPSTIKiWhmrNVokfxj4GKrIxMMslnmQczEcRcPZjNgyyiKyBqYaAWiUjuQ8bbCLe8L0LBrQUZmR4jvB/s1600/ShippingMethod.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu48TxagqOx-h22sjH34q86tVxex5jS96gN6l0Cj03HPMKElNdbD_Xwu0MwaYk_IPSTIKiWhmrNVokfxj4GKrIxMMslnmQczEcRcPZjNgyyiKyBqYaAWiUjuQ8bbCLe8L0LBrQUZmR4jvB/s1600/ShippingMethod.PNG" data-original-width="606" data-original-height="286" /></a></div>
<p>Ouch! A bit hard to justify $116.49 shipping on a $25 purchase. To be fair, I checked it again today while writing this post and they now have some much more reasonable options via USPS starting at $16.33 USD.</p>
<p>Anyway, as luck would have it I found some time to sit down in the Dreamforce '17 Developer Forest and start working through the project on site with the provided hardware. For some reason that I can't recall I opted to work through this module with an existing Developer edition org (lack of time to delete and then create a new trail org?). It was also my downfall, as the org had a namespace defined and the IoT Contexts didn't seem to support namespaces. There were GACKs all over the place. Lesson learned, next time I'll be tackling it against a clean org.</p>
<p>Fast forward to today, some months after Dreamforce and I've got some spare time to sit down and tackle this again. An no, I haven't forgotten the second thing that was holding me back. I'm just getting to that now.</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifWgFUhsq9_dG5zdt_Kycgs3ZTaQOfNFjSta4Qr7AzoEUGqGV5nXTrl8RVIG8gY-lHs86aBC8VUB0ddHA_bGbJ3pT4NN1kX0gyoI9_gP2ahIoek_JROdT5gCILGRlC6OyXc8QWHslfXrNS/s1600/20180301_215033.jpg" imageanchor="1" style=" float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifWgFUhsq9_dG5zdt_Kycgs3ZTaQOfNFjSta4Qr7AzoEUGqGV5nXTrl8RVIG8gY-lHs86aBC8VUB0ddHA_bGbJ3pT4NN1kX0gyoI9_gP2ahIoek_JROdT5gCILGRlC6OyXc8QWHslfXrNS/s320/20180301_215033.jpg" width="180" height="320" data-original-width="900" data-original-height="1600" /></a></div>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEig7wvHrqpUO_-1u-_L4TNs9q14U1IrRNitqR9OcRJ16epB_c5kSdG-y-KC-EDZMT606YB_zNj4ws2kgVPd-F1C24fxMFaprRylh_teTAMUO4nAgrRF9_ayDc_q_Dx5HNcdq1gwlLX-uP9F/s1600/20180301_215024.jpg" imageanchor="1" style=" float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEig7wvHrqpUO_-1u-_L4TNs9q14U1IrRNitqR9OcRJ16epB_c5kSdG-y-KC-EDZMT606YB_zNj4ws2kgVPd-F1C24fxMFaprRylh_teTAMUO4nAgrRF9_ayDc_q_Dx5HNcdq1gwlLX-uP9F/s320/20180301_215024.jpg" width="180" height="320" data-original-width="900" data-original-height="1600" /></a></div>
<p>I needed a fridge to use for the project. One that also got a good WiFi connection. I don't know about you, but my actual fridge is a bit of a WiFi dead zone. It's probably either the proximity of the microwave or the Faraday cage I wrapped it in to protect my ripe avocados from EMP attacks. This was an easy enough problem to solve. Like anyone else with a 3D printer, the solution was only several hours of plastic extrusion away. It turns out there was a purpose made fridge ready to go on Thingiverse- <a href="https://www.thingiverse.com/thing:2645340">Model Fridge for Salesforce IoT Electric Imp Developer Board</a>.</p>
<p>With my new mini fridge, electric imp board, and three AA-batteries-I-borrowed-from-my-sons-remote-control-car-but-will-replace-before-he-wakes-up I embarked on completing the project.</p>
<p>There appears to be two general ways to approach this trailhead project. You can either follow the instructions carefully and double check everything as you go (my chosen path), or you can just jump through pressing <button style="color: #fff;background: #3c9040;min-height: 25px;padding: 0 1rem;border-radius: 5px; border: 0 none;" onclick="alert('Winner, winner, chicken dinner!');">Verify Step</button> as fast as you can because each step ends with the statement:</p>
<blockquote>We won’t check any of your setup. Click <b>Verify Step</b> to go to the next step in the project.</blockquote>
<p><b>Boo!</b> This is actually a real pain, as there isn't anything to indicate if you've taken a misstep at any point along the way.</p>
<p>That said, it is all fairly straight forward if you are proficient at following instructions plus cutting and pasting.</p>
<p>The IoT orchestrations were new to me and hence the most challenging part of the project. For instance, I initially found it confusing that the conditions you define on a State are the exit criteria that transition to the other states. I guess this makes sense as a finite-state machine would only be concerned with the transitions it can make from the current state. E.g. If I'm in a door open state, I'm only interested in transitioning back to the default state when the door is closed again.</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpZVzncme6eBSPcKohTkqXQqvknDEjhuNc6s4wY6dvwuWxHjcYCShco4ONjj1RW1aETCdV_mDZyCT1OEgZRMYrjvEbi6fFyG6WqUHjF0xtrV1IjpUEHRfJk5JG-PFquczwh0zDg3bRdlox/s1600/DoorOpen.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpZVzncme6eBSPcKohTkqXQqvknDEjhuNc6s4wY6dvwuWxHjcYCShco4ONjj1RW1aETCdV_mDZyCT1OEgZRMYrjvEbi6fFyG6WqUHjF0xtrV1IjpUEHRfJk5JG-PFquczwh0zDg3bRdlox/s400/DoorOpen.PNG" width="400" height="83" data-original-width="992" data-original-height="205" /></a></div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4jix7acm6F6jDhTemkUKvT_YLiD0ghsjsmOnKL5v7fvHPXm5xFRpkvg4QG2JrsQx9-qBRL0rs37O9aAruT8pkjWkDMeEYXsBnLUgw2MCQjon8_7nRES5PIwRVr9aRVtkodmqlKZmDyjtp/s1600/OverTemperature.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4jix7acm6F6jDhTemkUKvT_YLiD0ghsjsmOnKL5v7fvHPXm5xFRpkvg4QG2JrsQx9-qBRL0rs37O9aAruT8pkjWkDMeEYXsBnLUgw2MCQjon8_7nRES5PIwRVr9aRVtkodmqlKZmDyjtp/s400/OverTemperature.PNG" width="400" height="178" data-original-width="878" data-original-height="390" /></a></div>
<p>As the Electric Imp is communicating to Salesforce via Platform Events it provided an easy mechanism to send in mock readings via Apex. This helped with testing when your child wanted the AA batteries back.</p>
<pre class='brush: java'>
Smart_Fridge_Reading__e mockReading = new Smart_Fridge_Reading__e();
mockReading.deviceId__c = '23733t1ed87bf1ee';
mockReading.door__c = 'Closed';
mockReading.humidity__c = 10.441;
mockReading.temperature__c = 8.6859;
mockReading.ts__c=DateTime.now();
EventBus.publish(mockReading);
</pre>
<p>Things I'd change? I'd probably take the light sensor LUX reading and relay that directly back to Salesforce rather than having a configured level to indicate that the door is open. I'm assuming it has the current form to show how values can be passed back from the Device to the Agent for additional processing. I'm also interested in the <a href="https://developer.electricimp.com/hardware/resources/reference-designs/explorerkit/#impexplorer-kit-sensors">accelerator and air pressure sensor</a> which are part of the imp001 hardware but aren't utilized in this badge. Maybe another state if the fridge door is closed too hard?</p>
<hr/>
<p>If you go away from the project for several days you might get the following error message from the Agent code:</p>
<blockquote>
[Agent] ERROR: [ { "message": "Session expired or invalid", "errorCode": "INVALID_SESSION_ID" } ]
</blockquote>
<p>In my case that was caused by the agent code persisting the access_token that it gets via the initial OAuth process. There isn't an automated mechanism to drop the expired session details or refresh it. Instead you need to use the Agent URL to complete the OAuth process again.</p>
<p>See <a href="https://github.com/electricimp/Salesforce/issues/13">Expired OAuth details being restored by getStoredCredentials()</a></p>
<hr/>
<p>Other related Trailhead modules:</p>
<ul>
<li><a href="https://trailhead.salesforce.com/en/modules/platform_events_basics">Platform Events Basics</a></li>
<li><a href="https://trailhead.salesforce.com/en/modules/iot_explorer_basics">Salesforce IoT Explorer Edition Basics</a></li>
</ul>
FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-56612378102138890812017-11-17T22:37:00.000+13:002017-11-28T08:36:05.171+13:00Dreamforce 2017 Round-up / Summary<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;">
<figure style="clear: right; float: right; background: #222222; -webkit-margin-start: 0px; -webkit-margin-end: 0px;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSw0g1Aw5EZeMS2MjQsvLgTP5ewCmvWzcTAumKADVvDUsS_Bxn2eDy6vBlxfksx_0CX8lsAWHGHkReSRctPOUvKZGDyYsZP75caCgKm1oAsTgFLZ4L4szWuWCDqJLU_SkB69JItd2Rzujn/s1600/HoldingOntoAgenda.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSw0g1Aw5EZeMS2MjQsvLgTP5ewCmvWzcTAumKADVvDUsS_Bxn2eDy6vBlxfksx_0CX8lsAWHGHkReSRctPOUvKZGDyYsZP75caCgKm1oAsTgFLZ4L4szWuWCDqJLU_SkB69JItd2Rzujn/s320/HoldingOntoAgenda.png" width="320" height="245" data-original-width="1120" data-original-height="858" /></a>
<figcaption>My carefully curated session agenda. It didn't last long.</figcaption>
</figure>
</div>
<p>In what is becoming a <a href="http://www.fishofprey.com/2016/10/dreamforce-2016-round-up-summary.html">tradition for me</a> I went into Dreamforce 2017 with a wildly optimistic 72 breakouts, theater sessions, and keynotes bookmarked that I wanted to attend. Like Codey desperately holding onto the clock on the Agenda page, I knew that was never going to work.</p>
<p>Instead I had a few key sessions and keynotes that I knew I wanted to attend. Beyond that, I just tried to go with the flow of the conference and to focus on doing things that I knew I could only do there in person.</p>
<p>It was certainly several whirlwind days that I'm only just now starting to piece back together from a trail of photos on my phone and tweets. Even seeing some of it coalescing in a single blog post is somewhat daunting assemblage.</p>
<!--Which reminds me - to the person who stopped me on the street who-->
<h2 style="clear: both;">Table of Contents</h2>
<ol>
<li><a href="#preconference">Preconference</a></li>
<li><a href="#astro">Self Driving Astro in the IoT Grove</a></li>
<li><a href="#day1">Day One</a>
<ul>
<li>Mini Hacks</li>
<li>Main Keynote</li>
</ul>
</li>
<li><a href="#day2">Day Two</a>
<ul>
<li>Mass Actions, Composite, and Bulk APIs</li>
<li>Salesforce Platform Limits</li>
<li>Developer Keynote</li>
<li>Meet the Apex Developers</li>
<li>Dreamfest</li>
</ul>
</li>
<li><a href="#day3">Day Three</a>
<ul>
<li>Advanced Logging Patterns With Platform Events</li>
<li>Build Custom Setup Apps & Config Tools With the All-New Apex Metadata API</li>
<li>The Future of Salesforce DX</li>
<li>True to the Core</li>
<li>Meet the Developers</li>
</ul>
</li>
<li><a href="#day4">Day Four</a>
<ul>
<li>Lightning Round Table</li>
<li>Salesforce Tower</li>
</ul>
</li>
<li><a href="#peanutButter">Walking Peanut butter distributor</a></li>
<li><a href="#random">Random Photos</a></li>
</ol>
<hr/>
<h2 style="clear: both;" id="preconference">Preconference</h2>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg07SAbsSiIOs8pUd6YRUv3FqXVPdYxWt1mAh8JFlrZvOwQQ5ItuPYyr70feJcNblv4ZqrbsuvKLMJyibe9bj4l0P9t-ZIOICvb2kWp9K6n3Tvg6O9x3k1RX5iNpPt_BI0pUZlce_aDU8mH/s1600/20171105_131601.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg07SAbsSiIOs8pUd6YRUv3FqXVPdYxWt1mAh8JFlrZvOwQQ5ItuPYyr70feJcNblv4ZqrbsuvKLMJyibe9bj4l0P9t-ZIOICvb2kWp9K6n3Tvg6O9x3k1RX5iNpPt_BI0pUZlce_aDU8mH/s320/20171105_131601.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a></div>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhO2dinPgqtCAkoIkaCTxHGfC7C6ehT7yAtOFmqFOtJA7YjGltHWNNODBsHYRPb1By3X5TSteMQFRz5U8zLvpVyHDyuGyW-ipzwYV8xC3N91LhtIE661esI_aVC9nOwBQi8rNOaNI-ScjQt/s1600/20171105_131608.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhO2dinPgqtCAkoIkaCTxHGfC7C6ehT7yAtOFmqFOtJA7YjGltHWNNODBsHYRPb1By3X5TSteMQFRz5U8zLvpVyHDyuGyW-ipzwYV8xC3N91LhtIE661esI_aVC9nOwBQi8rNOaNI-ScjQt/s320/20171105_131608.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a></div>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEib-noPUptcEUcvub12iPWwysoaXTDW829Q8PTrFIG5kenqZCDiPUUC19j4kXG-4-K3d6GqQ_PdxTNoQkL5Sskobzs6ZYmy1KxD7zEGQvb-kpyzzBE9zvwp2bFW3tUnbORKgsfloHF0_-O8/s1600/20171105_192313_tower.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEib-noPUptcEUcvub12iPWwysoaXTDW829Q8PTrFIG5kenqZCDiPUUC19j4kXG-4-K3d6GqQ_PdxTNoQkL5Sskobzs6ZYmy1KxD7zEGQvb-kpyzzBE9zvwp2bFW3tUnbORKgsfloHF0_-O8/s320/20171105_192313_tower.jpg" width="320" height="192" data-original-width="1600" data-original-height="962" /></a></div>
<p style="clear: right;">According to my phone the first on the ground Dreamforce thing I did after picking up my badge was head into Moscone West. Pretty much business as usually, <i>except it was the Sunday before the conference opened</i>.</p>
<p>I was there to setup my Self Driving Astro. More on that <a href="#astro">below</a>.</p>
<p>It was an interesting glimpse into what goes into setting up such a massive conference. There were <b>a lot</b> of people working hard and putting in some big hours to get everything setup and going in time of the opening the following morning.</p>
<p>On Sunday afternoon I also participated in the MVP volunteering event</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Perfect way to kick off <a href="https://twitter.com/Dreamforce?ref_src=twsrc%5Etfw">@Dreamforce</a>! Volunteering with the MVPs at E.R. Taylor Elementary School warms my ❤️ <a href="https://t.co/FPz6bWuksh">pic.twitter.com/FPz6bWuksh</a></p>— ericakuhl (@ericakuhl) <a href="https://twitter.com/ericakuhl/status/927414216578887682?ref_src=twsrc%5Etfw">November 6, 2017</a></blockquote>
<h2 id="astro" style="clear: both;">Self Driving Astro in the IoT Grove</h2>
<p>Way back in April this year after giving my <a href="http://www.fishofprey.com/2017/03/the-mad-catter-salesforce-predictive.html">automated Einstein powered cat sprinkler talk</a> to the Sydney Developer User Group I'd latched onto the idea to use the Einstein Vision Services to make a rudimentary self driving car. It was an itch that needed to be scratched. So I started working on it on and off since then and submitted it as a possible talk for Dreamforce.</p>
<p>Sadly it didn't get accepted as a talk this year. I suspect it was a little too far off the actual promoted use cases for the Einstein services. So while it was fun in concept, it could have lead to some confusion with customers about what the Salesforce offerings would be used for. Contrast it to something like the <a href="https://success.salesforce.com/Sessions?eventId=a1Q3A00000stRRuUAM#/session/a2q3A000001yuqDQAQ">Identify Protein Structures Using Einstein</a> talk, which sounds interesting in its own right and is on my list of sessions to catch up on.</p>
<p>It did leave me with a partially finished project that I'd put in all that effort and resources into. So rather than just mothball it I decided to carry on and make it a <a href="http://www.fishofprey.com/2017/10/teaching-salesforce-to-drive-with.html">blog post instead</a>. I'm glad I did, as it has been an excellent excuse to dive deep into the Metamind APIs and contribute to some GitHub projects along the way. It also formed part of an extended Einstien vision talk that I gave to the <a href="https://www.meetup.com/New-Zealand-Salesforce-Developer-Group/events/243903167/">Auckland Developer User Group</a>.</p>
<p>I published the blog post about it on the 20th of October. That was just over two weeks out from Dreamforce to avoid it getting lost in the noise of the conference. Then the next day Reid Carlberg asked if I was bringing it Dreamforce and if it could be setup on display. I jumped at the opportunity and set about reworking it from something that had only ever been run for 10 to 15 minutes at a time to something that would have to run continuously for 9+ hours a day. I had 11 days before I needed to be on my flight for Dreamforce.</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpxeJ-UyUSrf7_SMdfy0d7eieSPYkVaxym8eah3bTAhLJmSkiPUm0JPkcLIpabuIp9iDDXTwRb4m2DykVq0ub17xIUCa3YIOordZ_nalpURV9K7aJx6vcwgjx2ERwYLmzCY_tDKmDYQ1cu/s1600/AstroModel.PNG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpxeJ-UyUSrf7_SMdfy0d7eieSPYkVaxym8eah3bTAhLJmSkiPUm0JPkcLIpabuIp9iDDXTwRb4m2DykVq0ub17xIUCa3YIOordZ_nalpURV9K7aJx6vcwgjx2ERwYLmzCY_tDKmDYQ1cu/s320/AstroModel.PNG" width="320" height="314" data-original-width="709" data-original-height="695" /></a></div>
<p>Needless to say, it was a busy run up to departing for Dreamforce to:</p>
<ul>
<li>Print a new slightly larger seat,</li>
<li>Design and print a new steering column,</li>
<li>Upgrade to a larger metal gear servo,</li>
<li>Print a new steering wheel for the new servo,</li>
<li>Print a modified case for the Raspberry Pi to support the HAT and relay,</li>
<li>Design and print a case for the Larson Scanner board to prevent shorts,</li>
<li>Reinforce all the wiring to survive travel in checked luggage.</li>
</ul>
<p>Somehow it all came together in time along with a number of software updates to minimize the API counts and make the error handling more resilient. Many thanks to:</p>
<ul>
<li><a href="https://twitter.com/ReidCarlberg">Reid Carlberg</a> for the opportunity to set it up in the IoT Grove.</li>
<li><a href="https://twitter.com/MichaelEMachado">Michael Machado</a> for giving me a temporary bump on the Metamind API limits.</li>
<li><a href="https://twitter.com/joshbirk">Josh Birk</a> for helping to get it setup and running. Plus keeping an eye on it during the conference along with <a href="https://twitter.com/codefriar">@codefriar</a> and others in the IoT Grove.</li>
</ul>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Look who you can find driving away in the Moscone West IoT Grove at <a href="https://twitter.com/hashtag/DF17?src=hash&ref_src=twsrc%5Etfw">#DF17</a>. Insert your hand for Larson scanning. <a href="https://t.co/e4rXSL51rm">pic.twitter.com/e4rXSL51rm</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/927911085130235904?ref_src=twsrc%5Etfw">November 7, 2017</a></blockquote>
<h2 id="day1">Day One</h2>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLekn4PcNQn1ERWvtxbdXzPNvDliNiAugDHDKLFrB4xM9Wc_4F5YwMkC_9Sv8gquPJM4xJjrFbNqXKfw0suws0selYGTS3XDkAKmTyd1DwbuVhDOoKkGG5L7NchuVnO-_E4apK-u_LEk_l/s1600/20171106_074410.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLekn4PcNQn1ERWvtxbdXzPNvDliNiAugDHDKLFrB4xM9Wc_4F5YwMkC_9Sv8gquPJM4xJjrFbNqXKfw0suws0selYGTS3XDkAKmTyd1DwbuVhDOoKkGG5L7NchuVnO-_E4apK-u_LEk_l/s320/20171106_074410.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a></div>
<p>The first day went past in a bit of a blur. I was in and about the Mini hacks area volunteering during the morning and then over to the main keynote in the afternoon. In between I did a bit of exploring around Moscone West.</p>
<p>There were a number of areas touched on in the main keynote. In particular:</p>
<ul>
<li>the customization of <a href="https://www.salesforce.com/blog/2017/11/mylightning-lightning-customization">myLightning</a> to change the color themes and visual designs of the UX.</li>
<li><a href="https://www.salesforce.com/blog/2017/11/mysalesforce-branded-mobile-apps.html">mySalesforce </a> for creating mobile apps in Lightning.</li>
<li><a href="https://www.salesforce.com/blog/2017/11/mytrailhead-reinventing-trailblazer-learning.html">myTrailhead</a> for Trailhead customized to other companies.</li>
</ul>
<p>Also confetti - lots and lots of confetti.</p>
<blockquote class="twitter-video" data-lang="en"><p lang="en" dir="ltr">Confetti at the <a href="https://twitter.com/hashtag/DF17?src=hash&ref_src=twsrc%5Etfw">#DF17</a> keynote <a href="https://t.co/9ME0C5q5dS">pic.twitter.com/9ME0C5q5dS</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/927700779992891392?ref_src=twsrc%5Etfw">November 7, 2017</a></blockquote>
<h2 id="day2">Day Two</h2>
<p>The day started off with finding confetti from the keynote just about everywhere in my bag.</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Going into day two of <a href="https://twitter.com/hashtag/DF17?src=hash&ref_src=twsrc%5Etfw">#DF17</a> and taking handfuls of confetti out of my conference bag. <a href="https://twitter.com/hashtag/GoodConferenceProblems?src=hash&ref_src=twsrc%5Etfw">#GoodConferenceProblems</a> <a href="https://t.co/3xlFwoN3bh">pic.twitter.com/3xlFwoN3bh</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/927904555924254720?ref_src=twsrc%5Etfw">November 7, 2017</a></blockquote>
<h3 style="clear: both;">Mass Actions, Composite, and Bulk APIs</h3>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqqxXwMYg3nISC2baFiJLBk8rR9WZ1F-vhgHIVMPV3MFo41eZyd_9GxOJtQR5MVVfameQi395BurX4Pj-nMr7t28Wj3-2mBM-IYWGk1TuCDTbhp4Vk8T8LmDCnvjsG9u5NHtvweOgAGFk3/s1600/20171107_093648.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqqxXwMYg3nISC2baFiJLBk8rR9WZ1F-vhgHIVMPV3MFo41eZyd_9GxOJtQR5MVVfameQi395BurX4Pj-nMr7t28Wj3-2mBM-IYWGk1TuCDTbhp4Vk8T8LmDCnvjsG9u5NHtvweOgAGFk3/s320/20171107_093648.jpg" width="320" height="206" data-original-width="1600" data-original-height="1029" /></a></div>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUb7kGNxIJK3wmpi3ETqi4R9V8AWTGNOtmyA7fKZ3WbBDO_zIAxKGtvIkGlr58kjtblJSnlGdfzepJ8xEMV5maZElAFufSUjX4er8AHAxms1fpDSdSPabBWmeJoKsoFd9wdrdS2acLfCdN/s1600/20171107_093710.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUb7kGNxIJK3wmpi3ETqi4R9V8AWTGNOtmyA7fKZ3WbBDO_zIAxKGtvIkGlr58kjtblJSnlGdfzepJ8xEMV5maZElAFufSUjX4er8AHAxms1fpDSdSPabBWmeJoKsoFd9wdrdS2acLfCdN/s320/20171107_093710.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a></div>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYvzaqf2BBO2WopzDKRvoFrcIyYvPA3uEAnQcZfksyj8NxBZiTOdBRzOKajmGMEk-rtMJnp5ZPz-eJSPdixs9b4FwrmMrz70tU_82TC-g6YVmRDO1CzvXTF8Py_Wy3weih9PWC_9krQY_1/s1600/20171107_095411.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYvzaqf2BBO2WopzDKRvoFrcIyYvPA3uEAnQcZfksyj8NxBZiTOdBRzOKajmGMEk-rtMJnp5ZPz-eJSPdixs9b4FwrmMrz70tU_82TC-g6YVmRDO1CzvXTF8Py_Wy3weih9PWC_9krQY_1/s320/20171107_095411.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a></div>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEuUG5rJs-FyOt1UM0n3URqtmvPLX8jUTceV5TbnzXlIPZgfc2UPkGwmAXhSapnwy4f2enN9gcyjhD8cSkugf9Pl28RdAjUjSaQHEexP01__KS9sohyphenhyphen0IeRxbgsCBGsJtioWS7zWwUpjKh/s1600/20171107_122928.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEuUG5rJs-FyOt1UM0n3URqtmvPLX8jUTceV5TbnzXlIPZgfc2UPkGwmAXhSapnwy4f2enN9gcyjhD8cSkugf9Pl28RdAjUjSaQHEexP01__KS9sohyphenhyphen0IeRxbgsCBGsJtioWS7zWwUpjKh/s320/20171107_122928.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a></div>
<p style="clear: both;">I managed to catch my first full session today by <a href="https://twitter.com/thunderberry">@thunderberry</a> and <a href="https://twitter.com/abhinavchadda">@abhinavchadda</a>. While both the Bulk API v2 improvements and Open API support sound really useful, what intrigued me most was the proposed Mass Actions API. This could radically speed up a number of operations by defining a transform over a query. The exact details on how it will be split into transactions and how limits will be addressed is something to keep an eye on with this. </p>
<h3 style="clear: both;">Salesforce Platform Limits</h3>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4vjmCEfy13w618gArK3VFQLNQByYWUH8D2_6ej6sEhO28e5V0e7joKdgG7gBQLHC_mS0t4o3y0fwFtQSa_xFB1JKllnW8hxnaH5HeMjaLpfWELWEPOHc_OkE_6HJaASH2pTIxSiTZg2of/s1600/20171107_122019.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4vjmCEfy13w618gArK3VFQLNQByYWUH8D2_6ej6sEhO28e5V0e7joKdgG7gBQLHC_mS0t4o3y0fwFtQSa_xFB1JKllnW8hxnaH5HeMjaLpfWELWEPOHc_OkE_6HJaASH2pTIxSiTZg2of/s320/20171107_122019.jpg" width="320" height="181" data-original-width="1600" data-original-height="905" /></a></div>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_5TkU7_i5GWchdmADKE-GLIP4Z0SW3BPqC2pO3buNyP8BGW-TQTed3brcV6wJNbj45zKoe5LAIkc7hfiFwQb5dkv2IVYGTqSaEYJGxF3VSpRWcYlfK4p9F2N5z7yQ-SlL6oKtR0h2QPZk/s1600/20171107_122154.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_5TkU7_i5GWchdmADKE-GLIP4Z0SW3BPqC2pO3buNyP8BGW-TQTed3brcV6wJNbj45zKoe5LAIkc7hfiFwQb5dkv2IVYGTqSaEYJGxF3VSpRWcYlfK4p9F2N5z7yQ-SlL6oKtR0h2QPZk/s320/20171107_122154.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a></div>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_HSJF_iQ3x0k_C23xZWJtUyXFg6GLrqFPSF2VbWh3U2xS6BK3KUJ8-ANcoa3YPCZwV2AXfXGDCMKYcER7YJiVU7SsKC3TOZdnJSaXxMcEjybehttdbZGnLAd8fxBMeGfQG3B3GmDET24T/s1600/20171107_122248.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_HSJF_iQ3x0k_C23xZWJtUyXFg6GLrqFPSF2VbWh3U2xS6BK3KUJ8-ANcoa3YPCZwV2AXfXGDCMKYcER7YJiVU7SsKC3TOZdnJSaXxMcEjybehttdbZGnLAd8fxBMeGfQG3B3GmDET24T/s320/20171107_122248.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a></div>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTV_6mCbVNLMpT3o-32WAvH4im4_LE3-FPMjmrfz9ftcdC_zdbDgxR7vIZJrFzWU22iVhSDB_w1bQACgCk_FZ0Fw69w8cwdXPfaPKcEsG1nC5ig5rc0KRxyFiB1LFQLW4iALaeMY50i2eq/s1600/20171107_122638.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTV_6mCbVNLMpT3o-32WAvH4im4_LE3-FPMjmrfz9ftcdC_zdbDgxR7vIZJrFzWU22iVhSDB_w1bQACgCk_FZ0Fw69w8cwdXPfaPKcEsG1nC5ig5rc0KRxyFiB1LFQLW4iALaeMY50i2eq/s320/20171107_122638.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a></div>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXZsCooOo7JlHfr4crOMnm_t3SOUDOSvc6S8QGan1JcgXtBzU3Uh5o0T2Nwtz93XFVusqB10Pl1XrIK7Y0gJYWVUncCMbhjjymH_tWI879SiUvQ-pZvruFb9hlnTUNkXKVQTKiodnoFsQg/s1600/20171107_122855.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXZsCooOo7JlHfr4crOMnm_t3SOUDOSvc6S8QGan1JcgXtBzU3Uh5o0T2Nwtz93XFVusqB10Pl1XrIK7Y0gJYWVUncCMbhjjymH_tWI879SiUvQ-pZvruFb9hlnTUNkXKVQTKiodnoFsQg/s320/20171107_122855.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a></div>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-EHzXJFb7fj2rY-45ZEbzHCUx6JNVv1zrQakmUfg0A2YFVV6aswgUAuhbBMb5QNO9qGn25TDtEXNszj9d0z1sT2WCsIrYhoDQom7q2qNIzlDRExqYEIYAwV_Pq7D40ajZEeb-aQcXFWHZ/s1600/20171107_122928.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-EHzXJFb7fj2rY-45ZEbzHCUx6JNVv1zrQakmUfg0A2YFVV6aswgUAuhbBMb5QNO9qGn25TDtEXNszj9d0z1sT2WCsIrYhoDQom7q2qNIzlDRExqYEIYAwV_Pq7D40ajZEeb-aQcXFWHZ/s320/20171107_122928.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a></div>
<p style="clear: both;">This session was again with <a href="https://twitter.com/thunderberry">@thunderberry</a>. The proposal here is to move a number of existing limits to become "soft limits". Then depending on the pod heath you would be able to burst past the standard limit for short periods. There would still be an upper maximum burst limit. Consistently running past the soft limit will get you on a naughty list where Salesforce will encourage you to either upgrade or pin you to the existing limits. If the pod is particularly busy you would be more limited in what you could burst to. </p>
<p>This all sounds good in theory, but it will make debugging more difficult. Something that works within the soft limits one moment could fail the next due to the org load. This does seem a bit like the current Apex CPU limit.</p>
<p>A quick tip from this session:</p>
<blockquote>Don't poll the existing limits API to frequently. The calls to that still count against your API call count limit.</blockquote>
<h3 style="clear: both;">Developer Keynote</h3>
<p>The first thing that struck me about the Developer Keynote is what a fashionable bunch the developers are.</p>
<div class="separator" style="text-align: center;">
<figure style="clear: right; float: right; background: #222222; -webkit-margin-start: 0px; -webkit-margin-end: 0px;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuzoxgLviZ2a4hxKoXWl6UO7MHrvCBstX9vNPQ8aq8dPM6PZlTu-Ssm_ZkVDRfqz92_SN093EY5gVb-jmiAek3gsrjSGjg2csq4UfxevosUO7G13NnpE6FJ0-estIC2HvljUPfbyINKhHd/s1600/20171107_133639.jpg" imageanchor="1" style="margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuzoxgLviZ2a4hxKoXWl6UO7MHrvCBstX9vNPQ8aq8dPM6PZlTu-Ssm_ZkVDRfqz92_SN093EY5gVb-jmiAek3gsrjSGjg2csq4UfxevosUO7G13NnpE6FJ0-estIC2HvljUPfbyINKhHd/s320/20171107_133639.jpg" width="240" height="320" data-original-width="1200" data-original-height="1600" /></a>
<figcaption><a href="https://twitter.com/FishOfPrey/status/928013713935761408">Codey bear and Deployment Fish sweater.</a> <a href="https://twitter.com/WadeWegner/status/928034366810341376">Made by his dad.</a></figcaption>
</figure>
</div>
<div class="separator" style="text-align: center;">
<figure style="float: right; background: #222222; -webkit-margin-start: 0px; -webkit-margin-end: 0px;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHYs3mxg15t8IWlU5dwltcFnL_8y3BFmnSBIhDfYW54B5wVrQfIIdrINEYQu5EDraSXSnIGRlRN5ofpOxya4erFIrRN03N_tx60PMW5QLc-kRSD07_ApjQv19JzJG_viy92TzT10_2PVxG/s1600/20171107_135251.jpg" imageanchor="1" style=" margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHYs3mxg15t8IWlU5dwltcFnL_8y3BFmnSBIhDfYW54B5wVrQfIIdrINEYQu5EDraSXSnIGRlRN5ofpOxya4erFIrRN03N_tx60PMW5QLc-kRSD07_ApjQv19JzJG_viy92TzT10_2PVxG/s320/20171107_135251.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a>
<figcaption><a href="https://twitter.com/FishOfPrey/status/928018204525338625">df17__e - A Platform event shirt</a></figcaption>
</figure>
</div>
<div class="separator" style="text-align: center;">
<figure style="float: right; background: #222222; -webkit-margin-start: 0px; -webkit-margin-end: 0px;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeoJww15U_Q2xbvQvNzTmH8NIz-5EeTwYBhJuK3cF3TosHsttX5Vod6McTU6TamfoFpoF9eE_oXua4SFkgpSw2lRHdXOX8tif_ssvBOWdBPcid37_jcHiAkzO3NDxvpYQTTtQGfRcgOhYO/s1600/SuspiciousLookingPlant.gif" imageanchor="1" style="margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeoJww15U_Q2xbvQvNzTmH8NIz-5EeTwYBhJuK3cF3TosHsttX5Vod6McTU6TamfoFpoF9eE_oXua4SFkgpSw2lRHdXOX8tif_ssvBOWdBPcid37_jcHiAkzO3NDxvpYQTTtQGfRcgOhYO/s320/SuspiciousLookingPlant.gif" width="240" height="320" data-original-width="390" data-original-height="520" /></a>
<figcaption>A "Suspicious Looking Plant" and some Aloe vera.</figcaption>
</figure>
</div>
<p style="clear: both;">If time permits I'll come back to this section to recap some of the content.</p>
<h3 style="clear: both;">Meet the Apex Developers</h3>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">. <a href="https://twitter.com/slettehaugh?ref_src=twsrc%5Etfw">@slettehaugh</a> assures us at the <a href="https://twitter.com/hashtag/DF17?src=hash&ref_src=twsrc%5Etfw">#DF17</a> Meet the Apex developers session that switch statement support is at the top of the list now the new Apex compiler is out.</p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/928058959059025920?ref_src=twsrc%5Etfw">November 8, 2017</a></blockquote>
<p>I asked a question in this session about ENTERING_MANAGED_PKG appearing in debug logs and how it can frequently consume 80% plus of a 2MB log in a dev packaging org. They had been forewarned that this question was coming and thankfully the response was they are onto it and will be fixing the excess logging in the future. 🎉</p>
<h3 style="clear: both;">Dreamfest</h3>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgHWIuZyE-1Rxhyphenhyphenvkj7tjmou5rNtM8neRZKnvUxp_Hp6Pfr24TZyJ131HBn0GeXA9gHhSTqHN3YNegZ4p4MWrm-7RgNZ9QevsqmRDzMgBWiPk97xoVXAHo0x33TqY6f046tO3zeI2Ov0Qj/s1600/20171107_205543.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgHWIuZyE-1Rxhyphenhyphenvkj7tjmou5rNtM8neRZKnvUxp_Hp6Pfr24TZyJ131HBn0GeXA9gHhSTqHN3YNegZ4p4MWrm-7RgNZ9QevsqmRDzMgBWiPk97xoVXAHo0x33TqY6f046tO3zeI2Ov0Qj/s320/20171107_205543.jpg" width="320" height="110" data-original-width="1600" data-original-height="550" /></a></div>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">From the top of <a href="https://twitter.com/hashtag/DF17?src=hash&ref_src=twsrc%5Etfw">#DF17</a> Dreamfest <a href="https://t.co/Wws5WRe6R6">pic.twitter.com/Wws5WRe6R6</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/928120220878749696?ref_src=twsrc%5Etfw">November 8, 2017</a></blockquote>
<p>AT&T park made an excellent venue in terms of proximity to most of the hotels, visibility of the stage, and facilities for dealing with that many attendees.</p>
<h2 style="clear: both;" id="day3">Day Three</h2>
<h3><a href="https://success.salesforce.com/myagenda?eventId=a1Q3A00000stRRuUAM#/session/a2q3A000000GUyaQAG">Advanced Logging Patterns With Platform Events</a></h3>
<p>Using Platform Events to push logging events out and then monitoring them using a Utility Bar app.</p>
<h3><a href="https://success.salesforce.com/myagenda?eventId=a1Q3A00000stRRuUAM#/session/a2q3A000001ytx3QAA">Build Custom Setup Apps & Config Tools With the All-New Apex Metadata API</a></h3>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Watch your namespaces when using the Apex metadata API <a href="https://twitter.com/hashtag/DF17?src=hash&ref_src=twsrc%5Etfw">#DF17</a><a href="https://twitter.com/slettehaugh?ref_src=twsrc%5Etfw">@slettehaugh</a> <a href="https://t.co/zusb39Qolk">pic.twitter.com/zusb39Qolk</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/928341363988373505?ref_src=twsrc%5Etfw">November 8, 2017</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="in" dir="ltr"><a href="https://twitter.com/hashtag/DF17?src=hash&ref_src=twsrc%5Etfw">#DF17</a> Roadmap for Apex metadata API <a href="https://t.co/EW87hCDYo3">pic.twitter.com/EW87hCDYo3</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/928342214421372928?ref_src=twsrc%5Etfw">November 8, 2017</a></blockquote>
<h3><a href="https://success.salesforce.com/myagenda?eventId=a1Q3A00000stRRuUAM#/session/a2q3A000001ytBHQAY">The Future of Salesforce DX</a></h3>
<p>This session is well worth a repeat watch. Very dense on upcoming changes with DX. Mostly forward looking, but still interesting.</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">New Locked and Unlocked flavors of managed packages for distribution. <br>Future of Salesforce DX <a href="https://twitter.com/hashtag/DF17?src=hash&ref_src=twsrc%5Etfw">#DF17</a> by <a href="https://twitter.com/WadeWegner?ref_src=twsrc%5Etfw">@WadeWegner</a> <a href="https://t.co/gQThxX0Jij">pic.twitter.com/gQThxX0Jij</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/928355231275954176?ref_src=twsrc%5Etfw">November 8, 2017</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Better support coming to sandboxes to track changes and automated change set creation from that data. <a href="https://twitter.com/hashtag/DF17?src=hash&ref_src=twsrc%5Etfw">#DF17</a> <a href="https://twitter.com/hashtag/ForwardLooking?src=hash&ref_src=twsrc%5Etfw">#ForwardLooking</a> <a href="https://t.co/CyyGRJCbQ3">pic.twitter.com/CyyGRJCbQ3</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/928357406651719680?ref_src=twsrc%5Etfw">November 8, 2017</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">New Monaco and Language Services based web editor to use instead of Developer Console. <a href="https://twitter.com/hashtag/DF17?src=hash&ref_src=twsrc%5Etfw">#DF17</a> <a href="https://twitter.com/hashtag/FowardLooking?src=hash&ref_src=twsrc%5Etfw">#FowardLooking</a> <a href="https://t.co/WGhYl0oDHM">pic.twitter.com/WGhYl0oDHM</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/928359421821849600?ref_src=twsrc%5Etfw">November 8, 2017</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">UI for the CLI. Now accepting nominations for a better name. <a href="https://twitter.com/hashtag/DF17?src=hash&ref_src=twsrc%5Etfw">#DF17</a> <a href="https://t.co/LDbFSFTqym">pic.twitter.com/LDbFSFTqym</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/928359713607114752?ref_src=twsrc%5Etfw">November 8, 2017</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Improvements coming for Apex debug logs. Including streaming to get past the 2mb log size limit. <a href="https://twitter.com/hashtag/DF17?src=hash&ref_src=twsrc%5Etfw">#DF17</a> <a href="https://t.co/Hn4RVXIBA3">pic.twitter.com/Hn4RVXIBA3</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/928360459194966017?ref_src=twsrc%5Etfw">November 8, 2017</a></blockquote>
<h3><a href="https://success.salesforce.com/myagenda?eventId=a1Q3A00000stRRuUAM#/session/a2q3A000000GUwyQAG">Change Data Capture: Data Synchronization in the Cloud</a></h3>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Schema ID exposed via the change data capture events. Can be used to check metadata that existed when event occured. <a href="https://twitter.com/hashtag/DF17?src=hash&ref_src=twsrc%5Etfw">#DF17</a> <a href="https://t.co/KEtwUrOMgi">pic.twitter.com/KEtwUrOMgi</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/928369635388399616?ref_src=twsrc%5Etfw">November 8, 2017</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Change Data Capture roadmap <a href="https://twitter.com/hashtag/DF17?src=hash&ref_src=twsrc%5Etfw">#DF17</a> <a href="https://t.co/jTASYb3muj">pic.twitter.com/jTASYb3muj</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/928374840137887745?ref_src=twsrc%5Etfw">November 8, 2017</a></blockquote>
<h3>True to the Core</h3>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Field to field filters coming to reports. I can haz in SOQL as well? <a href="https://t.co/ute5are8nu">pic.twitter.com/ute5are8nu</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/928403172594352128?ref_src=twsrc%5Etfw">November 8, 2017</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Apex switch statement stated for <a href="https://twitter.com/hashtag/Summer18?src=hash&ref_src=twsrc%5Etfw">#Summer18</a> <a href="https://twitter.com/hashtag/TrueToTheCore?src=hash&ref_src=twsrc%5Etfw">#TrueToTheCore</a> <a href="https://twitter.com/hashtag/DF17?src=hash&ref_src=twsrc%5Etfw">#DF17</a> <a href="https://t.co/0hlAgWHuUs">pic.twitter.com/0hlAgWHuUs</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/928403493349552128?ref_src=twsrc%5Etfw">November 8, 2017</a></blockquote>
<h3>Meet the Developers</h3>
<div class="separator" style="clear: both; text-align: center;">
<figure style="clear: right; float: right; background: #222222; -webkit-margin-start: 0px; -webkit-margin-end: 0px;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6UJ1bcB1970cxKe5rwi6po-TcHIf8UJsZM47YuGVkqeL-eZdqSByfW8nvLrCIrpdFNho0gGrlJa2Kjddkts8jyPG63j3pnCixKgnGjWmvFndD-OGIMIITwkpNh3LAvdgkfngiPdsNt4nh/s1600/20171108_164241.jpg" imageanchor="1" style="margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6UJ1bcB1970cxKe5rwi6po-TcHIf8UJsZM47YuGVkqeL-eZdqSByfW8nvLrCIrpdFNho0gGrlJa2Kjddkts8jyPG63j3pnCixKgnGjWmvFndD-OGIMIITwkpNh3LAvdgkfngiPdsNt4nh/s320/20171108_164241.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a>
<figcaption>Steve Tamm rallying the troops prior to the Meet the Developers session</figcaption>
</figure>
</div>
<p>I asked a question in this session about raising support cases for GACKs and those without Premier support being turned away to the developer forums. If you have specific examples of this happening that you want to share please see <a href="https://salesforce.meta.stackexchange.com/q/2657/102">Examples of being bounced by Salesforce Support to forums when encountering a GACK</a></p>
<h2 style="clear: both;" id="day4">Day Four</h2>
<p>Today was a bit interrupted from attending sessions, but in a good way!</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Raw, real, and candid feedback on <a href="https://twitter.com/salesforce?ref_src=twsrc%5Etfw">@salesforce</a> Lighting happening in this room. The brain power is overwhelming! <a href="https://t.co/zODXrQJTq3">pic.twitter.com/zODXrQJTq3</a></p>— ericakuhl (@ericakuhl) <a href="https://twitter.com/ericakuhl/status/928689555519049728?ref_src=twsrc%5Etfw">November 9, 2017</a></blockquote>
<h3>Salesforce Tower - Ending Dreamforce on a high</h3>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Just going for a stroll down Mission to Fremont. Any chance you can hook us up <a href="https://twitter.com/hollygfirestone?ref_src=twsrc%5Etfw">@hollygfirestone</a>? <a href="https://t.co/aYFXwlskMD">pic.twitter.com/aYFXwlskMD</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/928738640456433664?ref_src=twsrc%5Etfw">November 9, 2017</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Awesome experience visiting the <a href="https://twitter.com/salesforce?ref_src=twsrc%5Etfw">@Salesforce</a> tower with some of our amazing Salesforce MVPs!! <a href="https://twitter.com/hashtag/df17?src=hash&ref_src=twsrc%5Etfw">#df17</a> <a href="https://t.co/lzTwtYRAtK">pic.twitter.com/lzTwtYRAtK</a></p>— Holly Firestone (@hollygfirestone) <a href="https://twitter.com/hollygfirestone/status/928755030999445504?ref_src=twsrc%5Etfw">November 9, 2017</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Thanks so much <a href="https://twitter.com/hollygfirestone?ref_src=twsrc%5Etfw">@hollygfirestone</a> for taking my crude plan constructed in a paint program and doing all the hard work to turn it into reality. It meant a lot to visit the SFO skyline from such an awesome building. <a href="https://t.co/xdzNLeQE28">pic.twitter.com/xdzNLeQE28</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/928775500624928769?ref_src=twsrc%5Etfw">November 10, 2017</a></blockquote>
<iframe width="560" height="315" src="https://www.youtube.com/embed/zElTTAVfuK4" frameborder="0" allowfullscreen></iframe>
<h2 style="clear: both;" id="peanutButter">Walking Peanut butter distributor</h2>
<p>This year I brought 3kg/6.6lb of <a href="https://www.picspeanutbutter.com">Pic's peanut butter</a> with me to give out to people. It's made right here in Nelson, New Zealand and I figured I'd be the only person giving out peanut butter at Dreamforce. At the very least it made for an interesting conversation starter. Not too many people thought I was the nutty one in the transaction (at least out loud).<br/> And to those with peanut allergies - no hard feelings, can we still be friends? I wasn't really trying to kill you.</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQ92oc7xV5Wzui-ijCVPIhyphenhypheng8KOrYnnLFN4x1dytknf7aJoKI-1qmf6FFwxXPBJIHjmOEwQMhdQ215Dx5pgXl457wcGzPGckPmEsQx9lipsY7qZyQVHpFWRHaLDO-d2Ohv4ElSnGGYkqW2/s1600/20171026_082812.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQ92oc7xV5Wzui-ijCVPIhyphenhypheng8KOrYnnLFN4x1dytknf7aJoKI-1qmf6FFwxXPBJIHjmOEwQMhdQ215Dx5pgXl457wcGzPGckPmEsQx9lipsY7qZyQVHpFWRHaLDO-d2Ohv4ElSnGGYkqW2/s320/20171026_082812.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a></div>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">I think I just get the best goodie of this <a href="https://twitter.com/Dreamforce?ref_src=twsrc%5Etfw">@Dreamforce</a>, thanks <a href="https://twitter.com/FishOfPrey?ref_src=twsrc%5Etfw">@FishOfPrey</a> <a href="https://twitter.com/FuseInfoTech?ref_src=twsrc%5Etfw">@FuseInfoTech</a> ! <a href="https://t.co/2dDjHARHc9">pic.twitter.com/2dDjHARHc9</a></p>— Fabien Taillon (@FabienTaillon) <a href="https://twitter.com/FabienTaillon/status/928055038668300288?ref_src=twsrc%5Etfw">November 8, 2017</a></blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr"><a href="https://twitter.com/FishOfPrey?ref_src=twsrc%5Etfw">@FishOfPrey</a> knew we were hungry, so he brought us yummy 🥜 butter <a href="https://twitter.com/hashtag/snacks?src=hash&ref_src=twsrc%5Etfw">#snacks</a>! Find him to avoid getting <a href="https://twitter.com/hashtag/hangry?src=hash&ref_src=twsrc%5Etfw">#hangry</a> at <a href="https://twitter.com/hashtag/DF17?src=hash&ref_src=twsrc%5Etfw">#DF17</a>! <a href="https://t.co/tDwf51waaO">pic.twitter.com/tDwf51waaO</a></p>— Gillian Bruce (@gilliankbruce) <a href="https://twitter.com/gilliankbruce/status/927973511062102016?ref_src=twsrc%5Etfw">November 7, 2017</a></blockquote>
<h2>Sessions I mean to catch up on</h2>
<iframe width="560" height="315" src="https://www.youtube.com/embed/videoseries?list=PL2v7tlhuOlyaWgrY4D_iHOHfyCMlDPgLM" frameborder="0" gesture="media" allowfullscreen></iframe>
<h2 style="clear: both;" id="random">Random Photos</h2>
<div class="separator" style=" text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwK3A0X6eWvQ6FGbe-vnB5-QS7dhXosShUlNEmx-upZfQaijUvF1eWUgGyF8k_jZQ2y7anBaw11CG5VnL-TZ8WTbMNLVI5rKBfUL0o51IjQOLusjl3LqK0NmTE-oXVxgtpIWTdZxIDFXk0/s1600/20171107_113101.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwK3A0X6eWvQ6FGbe-vnB5-QS7dhXosShUlNEmx-upZfQaijUvF1eWUgGyF8k_jZQ2y7anBaw11CG5VnL-TZ8WTbMNLVI5rKBfUL0o51IjQOLusjl3LqK0NmTE-oXVxgtpIWTdZxIDFXk0/s640/20171107_113101.jpg" width="640" height="317" data-original-width="1600" data-original-height="792" /></a></div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjItIih07snw6cimU0Cvl-fTc_N1H97M7PA4VQnWc77N_n1-AR67ZGt5_m1mKHpT8yUwavJqbbWLTTU2W5LPX5LJeU_OUqXKAW7_pnDjZE4bIk7o538_E_fAy1FQP3Sru4lv6bcbtffnF7c/s1600/20171106_121401.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjItIih07snw6cimU0Cvl-fTc_N1H97M7PA4VQnWc77N_n1-AR67ZGt5_m1mKHpT8yUwavJqbbWLTTU2W5LPX5LJeU_OUqXKAW7_pnDjZE4bIk7o538_E_fAy1FQP3Sru4lv6bcbtffnF7c/s320/20171106_121401.jpg" width="240" height="320" data-original-width="1200" data-original-height="1600" /></a>
<div class="separator" style=" text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7__JBXkGEmzo0RGyQPqIG8atadTmJ3uvGIZGTMgAKbeCFCzMnZ-5ZlqorOPSIJh6oKLZ81WPGcryF-NHbK1rLqtAie7138u6mZZ1Jmzihj2Q_Q_rb-sIzwK8HjOYY_tIUuWqmE_E9KgYW/s1600/20171106_194258.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7__JBXkGEmzo0RGyQPqIG8atadTmJ3uvGIZGTMgAKbeCFCzMnZ-5ZlqorOPSIJh6oKLZ81WPGcryF-NHbK1rLqtAie7138u6mZZ1Jmzihj2Q_Q_rb-sIzwK8HjOYY_tIUuWqmE_E9KgYW/s320/20171106_194258.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a></div>
<div class="separator" style=" text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW8Urf-RKt67wA6wdY8IrS-KqmZvx8NWoVjrpXS2WJDd9iaih0_nF0puSOQWGiMM1wo6moS_Jf_IxBbHJzP4m8Kbq_NlUAPXLGiowTNfpkbLIHuMZVhn_1UUTcRA7k9_EAC4dv05WL3YD1/s1600/20171108_080926.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW8Urf-RKt67wA6wdY8IrS-KqmZvx8NWoVjrpXS2WJDd9iaih0_nF0puSOQWGiMM1wo6moS_Jf_IxBbHJzP4m8Kbq_NlUAPXLGiowTNfpkbLIHuMZVhn_1UUTcRA7k9_EAC4dv05WL3YD1/s320/20171108_080926.jpg" width="320" height="163" data-original-width="1600" data-original-height="817" /></a></div>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHeegRUeggSnW6iy-jMngSu-LOHhuvkHPVTG090lt6bPdgABMVEPRM5h-vaPt3McagsXcVf6olHxFph89g6CENYInMWfS8n6BRm49j_m0anw4RnW8qfnXjIsZ4vIKBaQPGlVoBbYExt_eu/s1600/20171108_223555.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHeegRUeggSnW6iy-jMngSu-LOHhuvkHPVTG090lt6bPdgABMVEPRM5h-vaPt3McagsXcVf6olHxFph89g6CENYInMWfS8n6BRm49j_m0anw4RnW8qfnXjIsZ4vIKBaQPGlVoBbYExt_eu/s320/20171108_223555.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a></div>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZrmkg18DMRnwDNR4hyHz1m8vYVcTyPq69tcOnhY-E6N-lcLrYn9yR8PGE31AJmLcYN2m4DbazrZ_apuoeeJJONTIazhgEW4RZTqzY7CxBECoMGCDSjdRj9q-92tLOOraCkuFG5uYc0PL_/s1600/20171109_083023.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZrmkg18DMRnwDNR4hyHz1m8vYVcTyPq69tcOnhY-E6N-lcLrYn9yR8PGE31AJmLcYN2m4DbazrZ_apuoeeJJONTIazhgEW4RZTqzY7CxBECoMGCDSjdRj9q-92tLOOraCkuFG5uYc0PL_/s320/20171109_083023.jpg" width="240" height="320" data-original-width="1200" data-original-height="1600" /></a></div>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1HzAYLW0MZVoegP3k0qANzeAEPDxQkp9WvR5whyvh4ckpXkhQdSEmtKX5aeuwxGqnG3BsOqPUH7pprqNPwoycKuO7XTPK9eNXRCyJwaIR1TbTJKkBykJhWdOa-fpWv4_l7eiH2E3ppntV/s1600/20171109_124548.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1HzAYLW0MZVoegP3k0qANzeAEPDxQkp9WvR5whyvh4ckpXkhQdSEmtKX5aeuwxGqnG3BsOqPUH7pprqNPwoycKuO7XTPK9eNXRCyJwaIR1TbTJKkBykJhWdOa-fpWv4_l7eiH2E3ppntV/s320/20171109_124548.jpg" width="320" height="181" data-original-width="1600" data-original-height="904" /></a></div>
<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNNt40zShlDPOjzjpT0tZQ8bhdQo-CPMmJy7UfQucKgX6jQ5sP4rwutFB1e6vnNxypT0zNqum1ISduBgn48oVS0FxUbWdKIioEXIrWP5LftD9Gou7mnFpG89dWU00kR5IMUscv704QztBI/s1600/20171110_103120.jpg" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNNt40zShlDPOjzjpT0tZQ8bhdQo-CPMmJy7UfQucKgX6jQ5sP4rwutFB1e6vnNxypT0zNqum1ISduBgn48oVS0FxUbWdKIioEXIrWP5LftD9Gou7mnFpG89dWU00kR5IMUscv704QztBI/s320/20171110_103120.jpg" width="320" height="62" data-original-width="1600" data-original-height="311" /></a></div>
<div style="clear: both;">
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Mental note. Next Dreamforce - vacuum bags! <a href="https://t.co/nAaA83VDXI">pic.twitter.com/nAaA83VDXI</a></p>— Daniel Ballinger 🦈 (@FishOfPrey) <a href="https://twitter.com/FishOfPrey/status/935006640981516288?ref_src=twsrc%5Etfw">November 27, 2017</a></blockquote>
</div>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.comtag:blogger.com,1999:blog-7249827273468308081.post-18511524085526326282017-10-20T10:33:00.000+13:002017-10-20T13:34:00.793+13:00Teaching Salesforce to drive with Einstein Vision Services<p style="float:right;">tl;dr. <a href="#results">Skip to the results</a>.</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Technology is not good or bad. It is what we do with it that matters. AI is a gift! May we use it for the betterment of all mankind! <a href="https://t.co/E09tuBYCnZ">pic.twitter.com/E09tuBYCnZ</a></p>— Marc Benioff (@Benioff) <a href="https://twitter.com/Benioff/status/909269849171402754">September 17, 2017</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<!--div class="separator" style="clear: both; text-align: center;"><div style="margin-bottom: 1em; margin-left: 1em;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv4Xz6Jxa59rcWhTPhRtWJi_DRyr2WfVl4329daLrchhQg_A6XCKA5MIRfCp0RnoeVcnTyFTKo4nJYqvyIbb33Uneji18IbZW5pjNhAGl0oCeikmoZz6l99USGjuWY1ikiOzlDic-d6f77/s1600/TonyStarkCatWeapons.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv4Xz6Jxa59rcWhTPhRtWJi_DRyr2WfVl4329daLrchhQg_A6XCKA5MIRfCp0RnoeVcnTyFTKo4nJYqvyIbb33Uneji18IbZW5pjNhAGl0oCeikmoZz6l99USGjuWY1ikiOzlDic-d6f77/s320/TonyStarkCatWeapons.png" width="320" height="195" data-original-width="460" data-original-height="280" /></a></div></div-->
<div class="separator" style="clear: both; text-align: center;">
<figure style="clear: right; float: right; background: #222222; -webkit-margin-start: 0px; -webkit-margin-end: 0px;">
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv4Xz6Jxa59rcWhTPhRtWJi_DRyr2WfVl4329daLrchhQg_A6XCKA5MIRfCp0RnoeVcnTyFTKo4nJYqvyIbb33Uneji18IbZW5pjNhAGl0oCeikmoZz6l99USGjuWY1ikiOzlDic-d6f77/s320/TonyStarkCatWeapons.png" width="320" height="207" data-original-width="622" data-original-height="403" />
<figcaption>For your consideration, the <a href="http://www.fishofprey.com/2017/03/the-mad-catter-salesforce-predictive.html">Mad Catter</a></figcaption>
</figure>
</div>
<p>There's something in that tweet that speaks to me. Maybe it's time to pull a Tony Stark and take a new direction with my creations. Moving away from the world of <strike>weapons</strike> <a href="http://www.fishofprey.com/2016/08/integrating-uavdrone-remote-data.html">questionable</a> <a href="http://www.fishofprey.com/2017/03/the-mad-catter-salesforce-predictive.html">development</a> and more towards something for the public good. Something topical.</p>
<p>Tesla, Apple, Uber, Google, Toyota, BMW, Ford, these are just a few of the companies working on creating self-driving cars. Maybe I should dabble with that too.</p>
<p id="limitedResources">My first challenge was that my R&D budget doesn't stretch quite as far as the aforementioned companies. While they all have market values measured in the billions my resources are a little more modest. So the kiwi <a href="https://www.freshtakepublishers.com/blogs/news/new-zealand-colloquialisms-and-kiwi-slang-today-number-eight-wire-mentality">Number Eight Wire Mentality</a> will come into play when <a href="https://en.wikipedia.org/wiki/Lidar">LIDAR</a> isn't an option.</p>
<div class="separator" style="clear: both; text-align: center;"><div style="margin-bottom: 1em; margin-left: 1em;"><blockquote>
Steve Rogers: Big man in a suit of armor. Take that off, what are you?</br>
Tony Stark: Genius billionaire playboy philanthropist.
</blockquote></div></div>
<!--div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoD0ITHEbLdt1igskohxt2yAPAdG9fOYOj7CyKosOuQlnUo4L1DhPlVs1OhyphenhyphenjlDRs5qcsZBFO25vhVVyIcm1gFW423qwN9Lo83t5kcPfRRKPPWTUVL46fI8BwL6i1NCds_MXWhNdaoFVgs/s1600/CaveStark.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoD0ITHEbLdt1igskohxt2yAPAdG9fOYOj7CyKosOuQlnUo4L1DhPlVs1OhyphenhyphenjlDRs5qcsZBFO25vhVVyIcm1gFW423qwN9Lo83t5kcPfRRKPPWTUVL46fI8BwL6i1NCds_MXWhNdaoFVgs/s320/CaveStark.jpg" width="320" height="213" data-original-width="600" data-original-height="399" /></a></div-->
<div class="separator" style="clear: both; text-align: center;">
<figure style="clear: right; float: right; background: #222222; -webkit-margin-start: 0px; -webkit-margin-end: 0px;">
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoD0ITHEbLdt1igskohxt2yAPAdG9fOYOj7CyKosOuQlnUo4L1DhPlVs1OhyphenhyphenjlDRs5qcsZBFO25vhVVyIcm1gFW423qwN9Lo83t5kcPfRRKPPWTUVL46fI8BwL6i1NCds_MXWhNdaoFVgs/s1600/CaveStark.jpg" width="320" height="207" data-original-width="622" data-original-height="403" />
<figcaption>* Actual project did not require hammering an anvil... yet</figcaption>
</figure>
</div>
<p>It's another way I fancy myself a bit like Tony Stark. Less like the genius, billionaire, playboy Stark and more like trapped in a cave with only the resources at hand Stark. I'll make do with whatever I've got on hand. Some servos, a Raspberry Pi, an old web cam, a massive amount of cloud computing resources.</p>
<p>That last point is important, while Stark has J.A.R.V.I.S. I've got <a href="https://developer.salesforce.com/einstein#section_2">Einstein Platform Services</a>.</p>
<p>I don't have a background in AI as a Data Scientist. My AI exposure has been more from copious amounts of science fiction and that <a href="http://homepages.mcs.vuw.ac.nz/~elvis/db/Publications.shtml#COMP307">one trimester back in university</a> where I did a single paper. <!--But isn't that what university is for? Experimenting with new things to help "find yourself'?--> I'm assuming the depiction of AI in the media is <a href="https://media.giphy.com/media/yUlFNRDWVfxCM/giphy.gif">about as accurate as the depiction of computing in general</a>. So while it's fun to take inspiration from an 80's documentary on self driving cars the most useful learning from something like Knight Rider is that Larson scanners make AI's look cool (more on that later). </p>
<!--h2>Knight Rider - Astro Rider AstroLarson</h2-->
<!--p>Other parallels include:</p>
<ul>
<li>Moving away from the world of <a href="http://www.fishofprey.com/2017/03/the-mad-catter-salesforce-predictive.html">weapons development</a> </li>
<li>One other parallel I can draw that will particularly helpful for this process is access to a J.A.R.V.I.S. like AI that helps with problem solving. Only less sassy and more Einstien like. </li>
</ul-->
<h2>Elephant in the room</h2>
<p>This is probably a good point to pause for a minute and note that, yes, I <i><b>know</b></i> that a solely cloud based AI isn't the best option, or even a very good option, for an autonomous vehicle. An image classification AI would only be part of a larger collection of sensor input used to make a self driving car. Connectivity and latency issues will pretty much rule out any full scale testing or moving at significant speed. That, and, I don't think my vehicle insurance would cover crashing the family car while it was trying to navigate a tricky intersection by itself. But I want to see how far I can push it anyway with a purely optical solution using a single camera.</p>
<p>I know that a number of the components I'm using on the prototype are less than ideal. I.e. using continuous rotation servos rather than stepper motors which would have given a more precise measure of the distance traveled. See my earlier point <a href="#limitedResources">above</a> that I'm mostly working with what I've got on hand. Feel free to contact me if you have a spare sum of cash burning a whole in your pocket that you want to invest in something like this.</p>
<p>Remember, this is just supposed to be a Mark 1 prototype. If it starts to look promising it can be refined in the future.</p>
<h2>The Overly Simplistic Plan</h2>
<p>The general idea for a minimalistic vehicle is:</p>
<ol>
<li>A single forward facing web cam to capture the current position on the road and what is immediately ahead.</li>
<li>A Raspberry Pi to capture the image and process it.</li>
<li>Einstien Predictive Vision Services to identify what is in the current image and the implied probable next course of action to take.</li>
<li>Some basic servo based motor functions to perform the required movements.</li>
<li>Repeat from step (2)</li>
</ol>
<p>I say overly simplistic here in that it doesn't really localize the position of the vehicle in the environment or provide it with an accurate course to follow. Instead it just makes a best guess prediction based on what is currently seen immediately ahead. There is no feedback mechanism based on where the car was previously or how well it is following the required trajectory. </p>
<!--p>There are three important parts to this project.</p>
<ol>
<li>Identifying the current position of the vehicle with respect to the oncoming road. <a href="#positioning">Positioning</a></li>
<li>Identifying the next action to take. <a href="#predicting">Predicting</a></li>
<li>Putting together a hardware platform that can gather the required data for (1) and then move as required by (2).</li>
</ol-->
<!--h2 id="positioning">Positioning</h2>
<p>Given a single input, the current web cam image, can I identify what is immediately ahead of me on the "road".</p>
<h2 id="positioning">Positioning</h2-->
<h3>Hardware - Some assembly required</h3>
<div class="separator" style="clear: both; text-align: center;">
<figure style="clear: right; float: right; background: #222222; -webkit-margin-start: 0px; -webkit-margin-end: 0px;">
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwKZysVBsHhmLWAP-h-EjlarihD5j9LZC0PU5nvnmesbWQPuLMehY697aiqL-z-peMHTA4XwNr5lCWyGi9KEIoqILj1j5nqfqbkan5F9oZ8991gkxZGWpwSMHgLwKqx72o1WPbB81H6rwy/s320/knightrider.gif" width="320" height="207" data-original-width="622" data-original-height="403" />
<figcaption>The model for the Mk2 Prototype</figcaption>
</figure>
</div>
<p>In the ideal world I'd have repurposed an RC toy car that had full steering and drive capabilities already. Or even just 3D printed a basic car. This would have given a realistic steering behavior via the front wheels. Instead I've started out with skid steering and a dolly wheel on a lego frame. This was quick and easy to put together and drive with some servos from a <a href="http://www.fishofprey.com/2017/06/controlling-analog-pwm-servos-from.html">previous project</a>.</p>
<p>While simple is good for v1, it was still not without it's challenges.</p>
<p>The first problem was that I couldn't just go from zero to full power on the drive wheel servos. It tended to either damage the lego gears or send the whole vehicle rolling over backwards. I needed to accelerate smoothly to get predictable movement.</p>
<div class="separator" style="clear: both; text-align: center;">
<figure style="clear: right; float: right; background: #222222; -webkit-margin-start: 0px; -webkit-margin-end: 0px;">
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCLURvcXaxneGs1lAjvyXnKXTsdZ7kxT5-xkHOPcD5jUFCsGiMbd4p0nrDzdRSgUPw4KllpHO8nYj-LOMeb820rKIXi-e70hTBWacD6q_nknOOvgXhsW_W0xbR1E98qS4n-LLEkVW1CDFa/s320/20171004_210118.jpg" width="320" height="207" data-original-width="622" data-original-height="403" />
<figcaption>Custom LiPo based high drain power supply</figcaption>
</figure>
</div>
<p>Another challenge was providing a portable power source. Originally I was powering the whole setup off a fairly stock standard portable cellphone charger to power both the Pi and the servovs. However, when I powered up the servos to move forward the Raspberry Pi would reset. The voltage sag when driving the motors was enough to reset the Pi. I was able to work around this by using one of the LiPo (Lithium polymer) batteries from my quadcopters with a high C rating (they can deliver a lot of power quickly if required) and a pair of step down transformers. </p>
<h3 style="clear: both;">Software</h3>
<p>The standard software control loop is:</p>
<ol>
<li>Capture webcam image</li>
<li>Send image off to the Einstein Image service for the steering Model.</li>
<li>Based on the result with the highest probability, activate servos to move the vehicle</li>
<li>Repeat</li>
</ol>
<p>Capturing the image is fairly straight forward.</p>
<p>Since latency was already going to make fast movement impractical I opted to relay the calls via Salesforce Apex services. This made the authentication easier as I only needed to establish and maintain a valid session with the Salesforce instance to then access the Predictive Vision API via Apex. It also meant I didn't need to reimplement the metamind API and could instead use René Winkelmeyer's <a href="https://github.com/muenzpraeger/salesforce-einstein-platform-apex">salesforce-einstein-platform-apex Github project</a>. This already included workarounds for <a href="http://www.fishofprey.com/2017/04/steps-required-to-support-posting.html">posting multipart requests</a> required by the API.</p>
<h3>Training</h3>
<p>This is something that has evolved greatly since my last project using Einstein Vision Services on the <a href="http://www.fishofprey.com/2017/03/the-mad-catter-salesforce-predictive.html">automated sprinkler</a>. Previously you created a dataset from a pre-collected set of examples and then created your model from that to make the predictions with. If it needed refining you repeated the entire process. Now you can <a href="https://releasenotes.docs.salesforce.com/en-us/winter18/release-notes/rn_einstein_vision_feedback.htm">add feedback directly to a dataset</a> and retrain the model in-place with v2 of the Metamind API. No more adding all the same examples again.</p>
<p>I found it really useful to have four operating modes for the control software to facilitate the different training scenarios.</p>
<p>The first mode would kick in if no DataSet could be found. In these case the car would wait for input at each step. Using a wireless keyboard I could indicate the correct course of action to take. The image visible at the time would be captured and filed away with the required label. This made creating the initial DataSet much easier.</p>
<p>The second mode was used if the DataSet existed but didn't have a Model created yet. In this case the input I gave could be used to directly create examples. This mode wasn't so useful and I'd tend to skip it.</p>
<p>The third option applied if the Model could be found. In this case I could still indicate the correct course of action to take. If the model returned the expected prediction nothing further needed to occur. However, if the highest prediction differed from the expected result I could directly add the required feedback into the model.</p>
<p>The final forth mode was to use the model to make predictions and take action solely off the highest prediction returned.</p>
<h3>Control theory - PID control</h3>
<p>The earlier statement about the software action "Based on the result, activate servos to move the vehicle" is a gross simplification of what is required to have a vehicle follow a desired trajectory. In the real world you don't merely turn your vehicle full lock left or right to follow the desired course (what is referred to as bang-bang steering). Instead you make adjustments proportional to how far off the desired trajectory you are,
how rapidly you are approaching the desired trajectory, and finally, if there are any environmental factors that are affecting the steering of the vehicle.</p>
<p>This should be familiar to anyone who makes and flys quadcopters (<a href="https://www.youtube.com/watch?v=wzopjkW8y40">another interest of mine</a>). It's referred to as <a href="https://en.wikipedia.org/wiki/PID_controller">PID (proportional–integral–derivative) Control</a> and provides the automated mechanism to keep the vehicle/quadcopter at the desired state where the output needs to adapt to meet the desired input. The following video does an excellent job of explaining how it works.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/4Y7zG48uHRo?start=8" frameborder="0" allowfullscreen></iframe>
<p>With my v1 prototype the control loop speed is so slow and the positioning so basic that I'm practically going with bang-bang style steering. It is less than ideal as most scenarios require fine motor control to accurately follow the curve of the road ahead. Definitely something to look at improving in v2</p>
<h2 id="results">The prototype results</h2>
<h3>Training example</h3>
<iframe width="560" height="315" src="https://www.youtube.com/embed/IbnjkG0UrM4" frameborder="0" allowfullscreen></iframe>
<p>This video shows the feedback training process for an existing model. The initial model was created off a fairly small number of examples in the dataset. I then refined it with feedback whenever the top prediction didn't match what I indicated it should be.</p>
<p>I've added some basic voice prompts to indicate what is occurring as it mostly runs headless during normal operation.</p>
<h3>Self steering example</h3>
<p>In this video I'm using an entirely different dataset to the training example above. Getting single laps out of this setup was a bit of a challenge. The real world is far less forgiving than software when something goes wrong. Through trial an error I found it was really important to get the camera angle right to give the best prediction for the current position. It was also important to adjust the amount of movement per action. Trying to make large corrective movements, particularly around corners, would often result in getting irrecoverably off course. This comes back to the "bang-bang" style steering mentioned above.</p>
<p>I've edited out some of the pauses to make it more watchable. So don't consider this a real time representation of how fast it actually goes.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/xw0qMdQI5wU" frameborder="0" allowfullscreen></iframe>
<p>This process was also not without its share of failures. The following video shows a more realistic speed for the device and what happens when it misjudges the cornering.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/0Yfsh1_U2kA" frameborder="0" allowfullscreen></iframe>
<h2>Conclusions</h2>
<p>Lets start with the Million Dollar Question -</p>
<blockquote>Can I use this today to convert my car into an AI powered automated driving machine and then live a life of leisure as it plays taxi for the all the trips the kids need to make?</blockquote>
<p>Umm, no. Even if you're happy with it only being around 50% confident that it should go in a straight line rather than swerve off to the right on occasion there are still a number of things holding it back.</p>
<p>For example, while it could be extended to recognize a stop sign there is currently no way to judge how far away that stop sign is<a href="#1"><sup>1</sup></a>.</p>
<p>That's not even taking into account other things that real roads have, like traffic, pedestrians, roadworks, ... At least I'm still someway off before I need to start worrying about things like the <a href="https://en.wikipedia.org/wiki/Trolley_problem">Trolley car problem</a></p>
<h2>Future Improvements</h2>
<p id="1" name="1">A couple of days before this post came out Salesforce released the Einstein Object Detection API. It's very similar to the Image recognition API I used above except in addition to the identified label in the image it will also give you a bounding box indicating where it was detected. With something like this I could then guess the relative position of the object in question to the current camera direction and maybe even distance based on a know size and how large the bounding box is coming back as. Definitely something to investigate for the MK2.</p>
<!--Future improvements when pilot API's for object detection with position are added. Important things like, is there a stop sign ahead and how far away is it (based on size).</p>
<p>A bit ahead of my time. Still waiting on the required functionality to judge distance and object position. How far away is that stop sign? Is that a car up ahead in front of me or to the left? </p-->
<!--p>Refinements - How much of the input image does it need to be trained on and reacting to for basic locomotion? If only the bottom half of the screen shows road then I could crop the top half off for the purpose of predictions. Assumes driving on a level road. No hills. Signs up high.</p-->
<h2>See also</h2>
<ul>
<li>Youtube - <a href="https://www.youtube.com/watch?v=OFhRT5Gz3lk">Build Smarter Apps with Einstein Platform Services</a></li>
<li><a href="https://developer.salesforce.com/blogs/2017/10/use-einstein-object-detection.html">How to use Einstein Object Detection</a></li>
<li>Dreamforce 2017 Session: <a href="https://success.salesforce.com/Sessions?eventId=a1Q3A00000stRRuUAM#/session/a2q3A000001yuqDQAQ">Identify Protein Structures using Einstein</a> </li>
<li><a href="http://www.fishofprey.com/2017/03/the-mad-catter-salesforce-predictive.html">The Mad Catter</a> - Using Einstein Image Services to identify and spray cats with a sprinkler.</li>
<li>Trailmix - <a href="https://trailhead.salesforce.com/users/005500000060Y7FAAU/trailmixes/einstein-platform-services">Einstein Platform Services - 🤖</a></li-->
</ul>
<h2>Gallery</h2>
<div class="separator" style="clear: both; text-align: center;">
<figure style="float: right; background: #222222; -webkit-margin-start: 0px; -webkit-margin-end: 0px;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivcEpgtxo3DayHl3D1tiPOYXFOhDOKPYgqKNbInk7_JSBhZfjEemEuG0P6OIcmuAmS6OwQ6gOpKNo7KD6W4eaRtICIGAF7n3O6e81zOZWqAXeRJuVCNMXEKR755sHDbMpGhW7Ypu1qnTVO/s1600/20170629_204319.jpg" imageanchor="1" style="margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivcEpgtxo3DayHl3D1tiPOYXFOhDOKPYgqKNbInk7_JSBhZfjEemEuG0P6OIcmuAmS6OwQ6gOpKNo7KD6W4eaRtICIGAF7n3O6e81zOZWqAXeRJuVCNMXEKR755sHDbMpGhW7Ypu1qnTVO/s320/20170629_204319.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a>
<figcaption>Putting together a dedicated Pi Screen</figcaption>
</figure>
<figure style="float: right; background: #222222; -webkit-margin-start: 0px; -webkit-margin-end: 0px;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgR1pf4vQT8iY7Br6rJJ7RV4vKPK-Ws9M0GAPr5e6joTA9x-d2csckFnDmF6oKkdslSesBsb-KG6YIlPPNUTd5DdugzxymVS69KdFBt6J084r5-6uiTtzSg5_Ex5tYFvCusUR3e2E4fN5mD/s1600/20170917_110740.jpg" imageanchor="1" style=margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgR1pf4vQT8iY7Br6rJJ7RV4vKPK-Ws9M0GAPr5e6joTA9x-d2csckFnDmF6oKkdslSesBsb-KG6YIlPPNUTd5DdugzxymVS69KdFBt6J084r5-6uiTtzSg5_Ex5tYFvCusUR3e2E4fN5mD/s320/20170917_110740.jpg" width="240" height="320" data-original-width="1200" data-original-height="1600" /></a>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgI5r1FpDGMDLE5PMnI58m8pTwIqnkBx_UvusWSqRZH7Y9DUS3_IEMfhL2klksQWu0d_gDAhmJHoSIPhX4HRFKB6Nvm8m45IzbLRQL5GUxvvxF0dzbuuuIOjfVuUz9K4QiZnF3LKuVm7POu/s1600/20170917_062006.jpg" imageanchor="1" style="margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgI5r1FpDGMDLE5PMnI58m8pTwIqnkBx_UvusWSqRZH7Y9DUS3_IEMfhL2klksQWu0d_gDAhmJHoSIPhX4HRFKB6Nvm8m45IzbLRQL5GUxvvxF0dzbuuuIOjfVuUz9K4QiZnF3LKuVm7POu/s320/20170917_062006.jpg" width="240" height="320" data-original-width="1200" data-original-height="1600" /></a>
<figcaption>Astro sized 3D printed racing seat</figcaption>
</figure>
</div>
<div class="separator" style="text-align: center;">
<figure style="float: right; background: #222222; -webkit-margin-start: 0px; -webkit-margin-end: 0px;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9PqzpirP1KEwt-1_ymIZL1Y5ucZQ65IYaOwcG4j_T4BLxvnh3OJkfeHagvZc0HUwGCmmPpcCSluuXc5nyqxPXlvTpnEap5agXOYhi7yXMF4-wDFCA3Tcg718pmdzAj60kbjng6l3WQ2FO/s1600/20170919_210914.jpg" imageanchor="1" style="margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9PqzpirP1KEwt-1_ymIZL1Y5ucZQ65IYaOwcG4j_T4BLxvnh3OJkfeHagvZc0HUwGCmmPpcCSluuXc5nyqxPXlvTpnEap5agXOYhi7yXMF4-wDFCA3Tcg718pmdzAj60kbjng6l3WQ2FO/s320/20170919_210914.jpg" width="240" height="320" data-original-width="1200" data-original-height="1600" /></a>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjO8CdBA6CZN3YuV-xMpremO6_fRc-lO2aGUt_YTDtVtcnNTt8etMtXafpMWAp66V1LSBdJSxc6YWI8nN7fN3kseb7d1vOBAzBVb8IswDU2XLQK7G2lWQA4CLFc3BFu0GSwkR84vZyy4Nco/s1600/20170919_211515.jpg" imageanchor="1" style="margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjO8CdBA6CZN3YuV-xMpremO6_fRc-lO2aGUt_YTDtVtcnNTt8etMtXafpMWAp66V1LSBdJSxc6YWI8nN7fN3kseb7d1vOBAzBVb8IswDU2XLQK7G2lWQA4CLFc3BFu0GSwkR84vZyy4Nco/s320/20170919_211515.jpg" width="240" height="320" data-original-width="1200" data-original-height="1600" /></a>
<figcaption>Original clunky power setup. Result of clunky power setup</figcaption>
</figure>
</div>
<div class="separator" style="text-align: center;">
<figure style="float: right; background: #222222; -webkit-margin-start: 0px; -webkit-margin-end: 0px;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH9V34jp5LbRYwidYaJ3ghZeKsRZqWVIGJUy9OrmmOZPmqb8bnN7xbnTF3nejDU5rWWAmLJiIgJ5KUC-yarA7AQcg21Dw2aN-UYfnaoOfOjDN_rmgpFk7JqqzegQ_VVUpMRTMwrjHNvopN/s1600/20171002_211719.jpg" imageanchor="1" style="margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH9V34jp5LbRYwidYaJ3ghZeKsRZqWVIGJUy9OrmmOZPmqb8bnN7xbnTF3nejDU5rWWAmLJiIgJ5KUC-yarA7AQcg21Dw2aN-UYfnaoOfOjDN_rmgpFk7JqqzegQ_VVUpMRTMwrjHNvopN/s320/20171002_211719.jpg" width="240" height="320" data-original-width="1200" data-original-height="1600" /></a>
<figcaption>Creating the blue Larson scanner</figcaption>
</figure>
</div>
<div class="separator" style="text-align: center;">
<figure style="float: right; background: #222222; -webkit-margin-start: 0px; -webkit-margin-end: 0px;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsse_EHoPcG_Z59EeSoFAiuA9LrzW8pkJkP_Z25vVIp2lNrQTqEt-n1hB5FYUEBfHQeDwcVLObkNXAEh64wiAXTooBhGOFws-gvvwKhZd-qBZfoD_XZOclUH66SDl_GTRuWMiKeWJD5R0j/s1600/20170628_215734_1.gif" imageanchor="1" style="margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsse_EHoPcG_Z59EeSoFAiuA9LrzW8pkJkP_Z25vVIp2lNrQTqEt-n1hB5FYUEBfHQeDwcVLObkNXAEh64wiAXTooBhGOFws-gvvwKhZd-qBZfoD_XZOclUH66SDl_GTRuWMiKeWJD5R0j/s320/20170628_215734_1.gif" width="180" height="320" data-original-width="369" data-original-height="656" /></a>
<figcaption>Red Astro Larson Scanner</figcaption>
</figure>
</div>
<div class="separator" style="text-align: center;">
<figure style="float: right; background: #222222; -webkit-margin-start: 0px; -webkit-margin-end: 0px;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDqigcRLsaw7Lz7haSou9mHJphNJ9MyhaPvJmte_kAiTqQOmXJbK6P_0AprpaCiEbjPhYUikMuO_1cr4oBxgFdreT-ySBBuklLTzb8fUI5TcMVr_FCFLvrlElkKnF-56aZU1bVltM0wKnD/s1600/20171010_214658.jpg" imageanchor="1" style="margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDqigcRLsaw7Lz7haSou9mHJphNJ9MyhaPvJmte_kAiTqQOmXJbK6P_0AprpaCiEbjPhYUikMuO_1cr4oBxgFdreT-ySBBuklLTzb8fUI5TcMVr_FCFLvrlElkKnF-56aZU1bVltM0wKnD/s320/20171010_214658.jpg" width="240" height="320" data-original-width="1200" data-original-height="1600" /></a><figcaption>Training setup for driving from Google Street View</figcaption>
</figure>
</div>
<div class="separator" style="text-align: center;">
<figure style="float: right; background: #222222; -webkit-margin-start: 0px; -webkit-margin-end: 0px;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn4PMnvpFgsPDOqeHPxPsept3g9UXpDeXWsubDppHfJNS40CNhLpwOsWCy3lOSExDxiEjVO-JvzHczsy4z5fYG3UGWJEM5C8L1b5xqiNL7ZYikgRdw4uFAI-KAqxlEbGDNBnWW9JOEJiVO/s1600/20171015_122640.jpg" imageanchor="1" style="margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn4PMnvpFgsPDOqeHPxPsept3g9UXpDeXWsubDppHfJNS40CNhLpwOsWCy3lOSExDxiEjVO-JvzHczsy4z5fYG3UGWJEM5C8L1b5xqiNL7ZYikgRdw4uFAI-KAqxlEbGDNBnWW9JOEJiVO/s320/20171015_122640.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a>
<figcaption>Basic servo setup</figcaption>
</figure>
</div>
<div class="separator" style="text-align: center;">
<figure style="float: right; background: #222222; -webkit-margin-start: 0px; -webkit-margin-end: 0px;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgChpFWvf0DefqDITPcolwJFXGHhZmmmpYdNQBAn3GhMU1M9MzUBhxeKqzI3yFZ-5l3FDayDW8xt6ACPYCSf8-MliFI4vFwsILKUqEh7QOsLo_BIk6wLqgHWkBbTJmoxWfn7rzu5nrpq8dM/s1600/20171015_135157.jpg" imageanchor="1" style="margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgChpFWvf0DefqDITPcolwJFXGHhZmmmpYdNQBAn3GhMU1M9MzUBhxeKqzI3yFZ-5l3FDayDW8xt6ACPYCSf8-MliFI4vFwsILKUqEh7QOsLo_BIk6wLqgHWkBbTJmoxWfn7rzu5nrpq8dM/s320/20171015_135157.jpg" width="320" height="240" data-original-width="1600" data-original-height="1200" /></a>
<figcaption>Lipo battery loaded onto the frame with a mess of wiring</figcaption>
</figure>
</div>
<iframe width="560" height="315" src="https://www.youtube.com/embed/-ck-sMzvTAY" frameborder="0" allowfullscreen></iframe>
<!-- Tweet with #EinsteinAI -->FishOfPreyhttp://www.blogger.com/profile/14095711104515084650noreply@blogger.com