Andy in the Cloud

From BBC Basic to Force.com and beyond…


Leave a comment

New job, a tool update and a bit of coding reflection

Hello everyone! It’s been a little while since I last added a blog, and today is an exciting day. This post covers some personal news about a new chapter in my life, an update to one of my oldest tools, and a reflection on object-oriented programming that I recently encountered and wanted to share.

New Location and New Role

I am excited to share that after nearly 8 years in the USA, my family and I are back in the UK, and wow, did we choose a great time of year with some fantastic weather recently. With a new location comes a new role as well. I am thrilled to continue at Heroku within Salesforce, but this time in the role of VP, Developer Advocacy. As you can see from the picture, it’s not without the influence of one of my other fond pastimes! Warning: some craggle was involved!

In my new role, I’ll be engaging with the developer community, focusing on Heroku and, depending on the audience, how Heroku applies to the rest of the Salesforce portfolio as well. I am thrilled to return to coding, which brings me to my next topic! I’ve been working on an update to the long-standing Salesforce GitHub Deployment Tool, which has been dutifully hosted on Heroku and serving the community’s deployment requests since 2013. After a bit more testing, I will be releasing it later this month.

Screenshot

Upgrading older code

For those not aware, the Salesforce GitHub Deployment Tool allows you to easily add a button to your GitHub repository, enabling others to deploy your latest and greatest library or tool directly to their production or sandbox org. It is built with the Java Spring framework and uses some Salesforce libraries for the API connections. Since Salesforce routinely deprecates its older APIs, an upgrade was in order! Not only that, but I also chose to upgrade its Spring framework, which went largely to plan—apart from one hitch…

Learning: When overriding base class logic be careful

In OOP (object-oriented programming) languages, it’s a convention, of course, to allow overrides of base class methods to facilitate extensibility and reuse. However, with great power comes great responsibility. Consider the code below for a moment, knowing that the base class this class extends is actually from another library being upgraded. Spot anything that could potentially be an issue?

Screenshot

In the above case, once I upgraded the Spring framework, an important new part of the base class initialization was bypassed, resulting in a null pointer exception in the base class logic. It is, of course, perfectly optional when overriding a base class to call the base class logic or not, and this code specifically chose not to. This brings me to reflect on why some languages explicitly require base methods to be flagged as overridable—it’s because sometimes, just because you can, doesn’t mean you should.

The code above is not necessarily wrong; it did what was needed at the time, and my issue was par for the course when upgrading. Clearly, the base class permitted it at the time. It was an easy fix in the end, though it’s something I still want to revisit, as I plan to do more with the Spring library and some of its new AI integration features. The moral of this story, I guess, is to be careful when taking over too much control from a base class you don’t own—if its implementation details change, your assumptions may become invalid. It’s not always easy to avoid, but it’s something to consider.

Whats next?

With my new role, I’ll be doing more coding, writing and sharing so please keep an eye on this blog and of course the Heroku blog. The Heroku team are out and about at various events as well, so please drop by the events page on the Heroku website to check the latest. As for myself, if you are in the London area, I will be attending DevOpsDays London in September.

Andy


12 Comments

The Future of DLRS

Salesforce platform has long since had a place in my heart for the empowerment it brings to people who like to create. As a developer I love to create and feel the satisfaction in helping others. With Salesforce I can create without code as well. Now as much as I love the declarative side of building I do love to code!

In 2013 I found a way to magnify this feeling by closing the gap between coding and helping other creators, also known as Admin’s. This blog talks about a big next step in the future of the Declarative Lookup Rollup Summaries Tool or “Dolores” (short for DLRS) as the community refers to it – and how you can help.

SUPPORT: Declarative Lookup Rollup Summary (DLRS) Tool: This tool is open source and is supported by the community in a volunteer capacity.  Kindly please post your questions to the Trailblazer Community Group. Thank you!

Memory Lane…

DLRS was somewhat born out of a solution looking for a problem. Around the same time in 2013 I was playing around with the Metadata API, automating Setup aspects via Apex and building on the platform. In doing so I was discovering some of its declarative gaps. One such gap was the inability to define rollups that are not related to master detail relationships – resolving this within the platform itself required Apex and still does today. However, every now and again I tend to somehow see connections between things that are not always obvious – and maybe a little crazy – and so I wondered – what if an Admin tool generated and managed code?

I am also a frugal developer who likes to focus on the job at hand and thus look to open source when I can. After a quick internet search I found Abhinav Gupta’s open source Apex library LREngine, also known as Salesforce Lookup Rollup Summaries. This still required a developer to write an Apex Trigger, and  it also lacked a way to configure it without a developer. And so the neurons fired and “Declarative” Lookup Rollup Summaries tool was born! Over time LREngine received a number of enhancements via DLRS requirements and optimizations. The ways in which rollups could be invoked and configured was expanded around the library. The rest, as they say, is history!

DLRS Stats and a Realization…

There have been 39 releases to date, and I am proud to have had 18 GitHub contributors supporting the tool with amazing features, fixes and improvements. Along with an amazing Chatter Group on the Trailblazer Community with over 1140 members. DLRS has been installed in tens of thousands of orgs at this point. When I started the Chatter group I tried my best to answer each and every question. What I started to find is the community began to help the community, superstars like Jon LaRosa, Dan Donin and Jim Bartek and many others are so engaged and supportive its wonderful to see.

The reality though as over the past years my time and focus on the tool has not met the increasing and ongoing demand for the tool. Between holiday time coding I don’t feel it’s quite enough and the community and users of this tool deserve more. And so with mixed feelings I sent the following tweet – well actually my wife pressed the send button for me – she knows how much I love this tool and generally knows what’s best – so here we are!

DLRS needs a team, and you can help

TL:DR If you’d like to join a team of community members, helping to ensure the future of DLRS, email sfdo-opensource@salesforce.com for more information on how you can help.

It’s very important to me for it to remain open source, free to the community and get the love and attention it deserves. There are a number of duties managing it that cause me to become a bit of a bottleneck, such as packaging, and also some things that are only in my head around testing and the code base. So I originally reached out for a lead developer to help out.

I had some great responses from the Twitter post, but it was the suggestion to have the project managed as a community team as part of the Salesforce Open Source Commons Program which showed me another path. One that could ensure DLRS continues to thrive and expand well into the future. 

The OSC program provides a framework that wraps a great process and set of tools around open source projects, in partnership between community leaders and Salesforce. Learning about the OSC program made me realize that to ensure DLRS would truly be a sustainable and trusted package for it’s tens of thousands of users, more than a new lead developer would be needed. Maintaining a package like DLRS should be done by a team of volunteers, including those who can help others with support questions, those that want to help with docs, those that like to manage feature backlogs and more automated release processes – the list goes on. There are already eight open source projects involved with the program, ranging from managed packages to help Naval Volunteers (Ombudsman) with case management, to product support help videos, to DEI ecosystem improvement. The program hosts multiple training opportunities, and very popular Community Sprint events (like hackathons) throughout the year, to bring exposure and new volunteers to projects. 

Photo caption: Open Source Community Sprint participants, Philadelphia, October 2019

I have met with Cori O’Brien, Senior Manager of the Open Source Commons, who is very keen to share the benefits of the program further to the DLRS community and especially those that are keen to help in whatever way they can. If you would like to help or just learn more about the program, please drop an email to sfdo-opensource@salesforce.com and we will add you to a kick-off meeting to be held mid August.

Meanwhile – thank you all for the support you have given this tool – its been truly something I will be proud of for the rest of my life. I am very excited about this next step and rest assured I will be around to continue to contribute with the project – but most importantly so will many others!

SUPPORT: Declarative Lookup Rollup Summary (DLRS) Tool: This tool is open source and is supported by the community in a volunteer capacity.  Kindly please post your questions to the Trailblazer Community Group. Thank you!


9 Comments

Salesforce DX Integration Strategies

This blog will cover three ways by which you can interact programmatically with Salesforce DX. DX provides a number of time-saving utilities and commands, sometimes though you want to either combine those together or choose to write your own that fit better with your way of working. Fortunately, DX is very open and in fact, goes beyond just interacting with CLI.

If you are familiar with DX you will likely already be writing or have used shell scripts around the CLI, those scripts are code and the CLI commands and their outputs (especially in JSON mode) is the API in this case. The goal of this blog is to highlight this approach further and also other programming options via REST API or Node.js.

Broadly speaking DX is composed of layers, from client side services to those at the backend. Each of these layers is actually supported and available to you as a developer to consume as well. The diagram shown here shows these layers and the following sections highlight some examples and further use cases for each.

DX CLI

Programming via shell scripts is very common and there is a huge wealth of content and help on the internet regardless of your platform. You can perform condition operations, use variables and even perform loops. The one downside is they are platform specific. So if supporting users on multiple platforms is important to you, and you have skills in other more platform neutral languages you may want to consider automating the CLI that way.

Regardless of how you invoke the CLI, parsing human-readable text from CLI commands is not a great experience and leads to fragility (as it can and should be allowed to change between releases). Thus all Salesforce DX commands support the –json parameter. First, let’s consider the default output of the following command.

sfdx force:org:display
=== Org Description
KEY              VALUE
───────────────  ──────────────────────────────────────────────────────────────────────
Access Token     00DR00.....O1012
Alias            demo
Client Id        SalesforceDevelopmentExperience
Created By       admin@sf-fx.org
Created Date     2019-02-09T23:38:10.000+0000
Dev Hub Id       admin@sf-fx.org
Edition          Developer
Expiration Date  2019-02-16
Id               00DR000000093TsMAI
Instance Url     https://customization-java-9422-dev-ed....salesforce.com/
Org Name         afawcett Company
Status           Active
Username         test....a@example.com

Now let’s contrast the output of this command with the –json parameter.

sfdx force:org:display --json
{"status":0,"result":{"username":"test...a@example.com","devHubId":"admin@sf-fx.org","id":"00DR000000093TsMAI","createdBy":"admin@sf-fx.org","createdDate":"2019-02-09T23:38:10.000+0000","expirationDate":"2019-02-16","status":"Active","edition":"Developer","orgName":"afawcett Company","accessToken":"00DR000...yijdqPlO1012","instanceUrl":"https://customization-java-9422-dev-ed.mobile02.blitz.salesforce.com/","clientId":"SalesforceDevelopmentExperience","alias":"demo"}}}

If you are using a programming language with support for interpreting JSON you can now start to parse the response to obtain the information you need. However, if you are using shell scripts you need a little extract assistance. Thankfully there is an awesome open source utility called jq to the rescue. Just simply piping the JSON output through the jq command allows you to get a better look at things…

sfdx force:org:display --json | jq
{
  "status": 0,
  "result": {
    "username": "test-hm83yjxhunoa@example.com",
    "devHubId": "admin@sf-fx.org",
    "id": "00DR000000093TsMAI",
    "createdBy": "admin@sf-fx.org",
    "createdDate": "2019-02-09T23:38:10.000+0000",
    "expirationDate": "2019-02-16",
    "status": "Active",
    "edition": "Developer",
    "orgName": "afawcett Company",
    "accessToken": "00DR000....O1012",
    "instanceUrl": "https://customization-java-9422-dev-ed.....salesforce.com/",
    "clientId": "SalesforceDevelopmentExperience",
    "alias": "demo"
  }
}

You can then get a bit more specific in terms of the information you want.

sfdx force:org:display --json | jq .result.id -r
00DR000000093TsMAI

You can combine this into a shell script to set variables as follows.

ORG_INFO=$(sfdx force:org:display --json)
ORG_ID=$(echo $ORG_INFO | jq .result.id -r)
ORG_DOMAIN=$(echo $ORG_INFO | jq .result.instanceUrl -r)
ORG_SESSION=$(echo $ORG_INFO | jq .result.accessToken -r)

All the DX commands support JSON output, including the query commands…

sfdx force:data:soql:query -q "select Name from Account" --json | jq .result.records[0].Name -r
GenePoint

The Sample Script for Installing Packages with Dependencies has a great example of using JSON output from the query commands to auto-discover package dependencies. This approach can be adapted however to any object, it also shows another useful approach of combining Python within a Shell script.

DX Core Library and DX Plugins

This is a Node.js library contains core DX functionality such as authentication, org management, project management and the ability to invoke REST API’s against scratch orgs vis JSForce. This library is actually used most commonly when you are authoring a DX plugin, however, it can be used standalone. If you have an existing Node.js based tool or existing CLI library you want to embed DX in.

The samples folder here contains some great examples. This example shows how to use the library to access the alias information and provide a means for the user to edit the alias names.

  // Enter a new alias
  const { newAlias } = await inquirer.prompt([
    { name: 'newAlias', message: 'Enter a new alias (empty to remove):' }
  ]);

  if (alias !== 'N/A') {
    // Remove the old one
    aliases.unset(alias);
    console.log(`Unset alias ${chalk.red(alias)}`);
  }

  if (newAlias) {
    aliases.set(newAlias, username);
    console.log(
      `Set alias ${chalk.green(newAlias)} to username ${chalk.green(username)}`
    );
  }

Tooling API Objects

Finally, there is a host of Tooling API objects that support the above features and some added extra features. These are fully documented and accessible via the Salesforce Tooling API for use in your own plugins or applications capable of making REST API calls.  Keep in mind you can do more than just query these objects, some also represent processes, meaning when you insert into them they do stuff! Here is a brief summary of the most interesting objects.

  • PackageUploadRequest, MetadataPackage, MetadataPackageVersion represent objects you can use as a developer to automate the uploading of first generation packages.
  • Package2, Package2Version, Package2VersionCreateRequest and Package2VersionCreateRequestError represent objects you can use as a developer to automate the uploading of second generation packages.
  • PackageInstallRequest SubscriberPackage SubscriberPackageVersion and Package2Member (second generation only) represent objects that allow you to automate the installation of a package and also allow you to discover the contents of packages installed within an org.
  • SandboxProcess and SandboxInfo represent objects that allow you to automate the creation and refresh of Sandboxes, as well as query for existing ones. For more information see the summary at the bottom of this help topic.
  • SourceMember represents changes you make when using the Setup menu within a Scratch org. It is used by the push and pull commands to track changes. The documentation claims you can create and update records in this object, however, I would recommend that you only use it for informationally purposes. For example, you could write your own poller tool to drive code generation based on custom object changes.

IMPORTANT NOTE: Be sure to consider what CLI commands exist to accomplish your need. As you’ve read above its easy to automate those commands and they manage a lot of the complexity in interacting with these objects directly. This is especially true for packaging objects.

Summary

The above options represent a rich set of abilities to integrate and extend DX. Keep in mind the deeper you go the more flexibility you get, but you are also taking on more complexity. So choose wisely and/or use a mix of approaches. Finally worthy of mention is the future of SFDX CLI and Oclif. Salesforce is busy updating the internals of the DX CLI to use this library and once complete will open up new cool possibilities such as CLI hooks which will allow you to extend the existing commands.


5 Comments

Custom Keyboard Shortcuts with Lightning Background Utilities

kbsexample2

As readers of my blog will know I am a big fan of the rich features the Lightning Experience UI provides to developers. Having blogged several times about the amazing Utility Bar, I have been keen to explore new possibilities with the new Background Utility feature. These are utilities that have no UI so do not use up space in the Utility Bar. Instead, they sit in the background monitoring things like other events generated by the user. One such documented use case is the possibility to monitor keyboard events! And so the Custom Keyboard Shortcut Component has been born! This component effectively runs Flows based on keyboard shortcuts defined by the admin! More on this later…

standardshortcuts.png

You may or may not know that Lightning Experience actually already provides some standard keyboard shortcut cuts? Just press Cmd+/ (Mac) or Ctrl+/ (Windows) to get a nice summary of them!

However, per the standard shortcut documentation, it’s not possible to add custom ones. By using the new lightning:backgroundUtilityItem interface we can rectify this. This blog explains a basic hardcoded example component and also introduces an open source component (installable package provided) that links admin defined keyboard shortcuts to Flows and certain navigation events.

In just a few lines of markup and JavaScript code you can get a basic example up and running.

<aura:component implements="lightning:backgroundUtilityItem" >
	<aura:handler name="init" value="{!this}" action="{!c.init}" />
</aura:component>

The component controller simply uses the standard addEventListener method. You can also inspect the keydown event properties to determine what keys are pressed, such as Shift or Control plus another key. This example simply determines if H is pressed and navigates to Home.

({
   init: function(component, event, helper) {
      window.addEventListener('keydown', function(e) {
      if (e.key === 'H') {
         $A.get('e.force:navigateToURL').fire({ url: '/lightning/page/home' })
      }
    });
  }
})

Once deployed go to the App Manager under Setup and add the component to the Utility Items list and that’s it! Note that the component has a different icon indicating it’s a non-visual component. Neat!

Of course, I could not simply leave things like this, so I set about making a more dynamic version. The configuration of the Custom Keyboard Shortcut component is shown at the top of this blog. It’s leveraging the fact that when you configure a Utility Bar component the App Manager inspects the .design file for the component to understand what attributes the component needs the user to configure. At runtime, the controller logic then parses the 9 attributes containing the keyboard shortcuts entered by the user into an internal map that is used by the keyboard event handler to match actions against keyboard activity.

Once you have installed the component either via a package install (admin friendly) or via sfdx force:source:deploy (devs). Add the component within the App Manager to configure keyboard shortcuts.

Through configuration you can connect keyboard shortcuts to the following:-

  • Open a UI Flow in a modal popup
  • Run an Autolaunch Flow
  • Display popup messages communicating the actions taken by the flow
  • Navigate the user to the Home tab
  • Navigate the user to records created by the flow

Further details on configuring the component can be found in the README here. Finally, you may recall that I used a Background Utility in this years Dreamforce presentation. In this case, it was using the new Streaming Component to listen to Platform Events. You can find the source code here.

Have fun!

 


12 Comments

Streaming Debug Logs to your console

Debug logs are a key tool in triaging and profiling on the Lightning Platform (formerly Force.com) both in development and production. While the Apex Interactive Debugger provides an interactive experience, sometimes you want to monitor, parse or filter logs. Maybe you are reproducing a bug and are watching for a certain SOQL query or method being executed or we just want filter output in different ways.

taillog.png

A recent addition to the DX command line from Chris Wall is the ability to effectively stream debug logs from any org connected to DX to the command line console. This is similar to the experience in Developer Console logs pane, but is effectively opening the logs and dumping them out as they are produced on the server for you automatically.

sfdx force:apex:log:tail

You can install the Salesforce DX CLI here. Note that you do not need to have a DX project to use this command.

In the following command line example, I have piped the output to another command (grep) that filters the output to show only USER_DEBUG log lines.

sfdx force:apex:log:tail --color | grep USER_DEBUG 

Pictures do not really do it justice, so here is a short demo video!

The command works against any org you have connected to the DX CLI, including production and sandbox orgs. However, if you run it from the same folder as a DX project it will use the currently configured default user/scratch org for that project.

Adding a bit of color to your debug logs!

The –color parameter used above enables some basic color highlighting for method, constructor, variable assignments etc.

colordebuglog.png

You can also customize your own colors by setting the SFDX_APEX_LOG_COLOR_MAP environment variable to an absolute file path to a JSON file per the format shown below.

{
    CONSTRUCTOR_: 'magenta',
    EXCEPTION_: 'red',
    FATAL_: 'red',
    METHOD_: 'blue',
    SOQL_: 'yellow',
    USER_: 'green',
    VARIABLE_: 'cyan'
}

Power to the pipe!

One of the most exciting features for me is the ability to pipe debug logs. Maybe you want to parse out some information to profile how many SOQL statements have been used or aggregate timestamp values (the bit in brackets after the time!) to do some performance profiling… I am looking forward to seeing what folks do with this, please share!

Anything else?

The –debugLevel command is optional but allows you to define your own debug level by inserting records into the TraceFlag object (via the DX CLI command force:data:record:create). Finally, you can run the command with the –help parameter to get the latest help.

Usage: sfdx force:apex:log:tail [-c] [-d ] [-s] [-u ] [--json] [--loglevel ] 

start debug logging and display logs

Flags:

 -c, --color                          colorize noteworthy log lines

 -d, --debuglevel DEBUGLEVEL          debug level for trace flag

 -s, --skiptraceflag                  skip trace flag setup

 -u, --targetusername TARGETUSERNAME  username or alias for the target org;

                                      overrides default target org

 --json                               format output as json

 --loglevel LOGLEVEL                  logging level for this command invocation

                                      (error*,trace,debug,info,warn,fatal)