My guy, this is the best thing Salesforce has added to the Apex language in forever! Embrace it! To elaborate on that though, let me hit you with this thrilling sales pitch. Just imagine a late night commercial selling you garbage, but the garbage is actually good.
Are you frustrated with the insane amount of null checking you have to do when writing your apex code? Do you wish there was a way you didn’t have to do a null to prevent your code from crashing and burning? Well Salesforce has a solution to that problem! The safe navigation operator! Starting with the Winter 21 release your dreams have finally come true! Erase all those null checks you were doing on your soql queries, your objects and so much more! Watch 4+ lines of code get condensed to a single line and enjoy your life as a Salesforce Developer just a little bit more!
Ok… enough of that, hopefully that sweet action sales pitch sold you, but if it didn’t let’s check out some code to hopefully convince you the safe nav operator is worth your time.
Safe Navigation Operator Code Examples
Before we get started, if you’d prefer to check out these examples on GitHub, you can see them here. Otherwise, let’s keep on keepin on. Let’s start with a soql example that doesn’t use the safe navigation operator. In this example we just want to get the name of an Account.
public static void noSafeNav(){
List<Account> acctList = [SELECT Id, Name FROM Account WHERE Name = 'Kevin' LIMIT 1];
if(!acctList.isEmpty()){
String acctName = acctList[0].Name;
}
}
As you can see above, to navigate safely without the risk of our code crashing from a null pointer exception or a, “list has no rows to assign to SObject” exception we need 4 lines of code. Not bad, but after awhile that can get tedious. Now let’s try to do the same thing with the safe navigation operator.
public static void safeNav(){
String acctName = [SELECT Id, Name FROM Account WHERE Name = 'Kevin' LIMIT 1]?.Name;
}
Oh dwamnnnnnnnnnnnnn, with the safe navigation operator we are able to do this in a single line of code… uhmazing. If you didn’t know the safe navigation operator is that question mark between the soql query and the .Name. Basically what the safe navigation operator does is check whether the query is null before trying to grab the name field from the SOQL query. If the query is null (or returns nothing), it will assign the value null to the acctName variable. This is super convenient and can reduce your codebase a ton.
Hopefully this example has convinced you it’s worth it to utilize the safe navigation operator but if it hasn’t there is a mapping example in the github repo too. It can also save you a ton of null checking with maps as well!
Get Coding With The Force Merch!!
We now have a redbubble store setup so you can buy cool Coding With The Force merchandise! Please check it out! Every purchase goes to supporting the blog and YouTube channel.
In short, it’s gonna save you a bunch of time, code and unnecessary configuration, especially when you are authenticating using OAuth. Named credentials basically simplify the authentication portion of your callouts to to external services and allow you do it declaratively through configuration. No matter how hardcode a dev you are, they are 100% worth your time and effort to learn how to use. I promise.
How do you setup a named credential?
You traverse to Setup -> Named Credentials to setup the named credential of your choosing. Named Credentials allow you to authenticate via the vast majority of the authentication methods used by external service providers. You will likely even be able to connect to your internal data bases via named credentials as well if you need to. I’m not gonna go over them all individually in this article. In the video above I got over three different Named credential types and how to configure them. If you’re interested in that portion, please check it out!
How do we reference named credentials in the code?
This literally could not be easier. In fact it’s so simple I think it confuses the hell out of some people, lol. I will give you a simple example below that connects to GitHub via OAuth:
public class GithubOAuthCallout {
public static void callGitHub(){
HttpRequest req = new HttpRequest();
req.setEndpoint('callout:GitHub_OAuth/users/Coding-With-The-Force/repos');
req.setMethod('GET');
req.setHeader('Accept', 'application/json');
req.setHeader('Content-Type', 'application/json');
Http http = new Http();
HTTPResponse res = http.send(req);
System.debug(res.getBody());
}
}
There are a couple of important things to point out in the code above:
1) When we are setting the endpoint for the HttpRequest we are add the value ‘callout:GitHub_OAuth’ this is how we reference our Named Credential. When you are setting your endpoints for your HttpRequests you pass in your Named Credential by using the following format: callout:[The name of your named credential].
2) If you’ve ever requested data using OAuth authentication you know that we seem to be missing a few steps… We’re not calling out to any authorization endpoints or getting an access token anywhere in the above code. We’re also not setting an authorization header parameter. THAT’S BECAUSE SALESFORCE DOES IT ALL FOR YOU AUTOMATICALLY! Yes… you read that right, automatically, no need to write that code yourself. That ‘callout:GitHub_OAuth’ is doing a ton of behind the scenes magic. It gets that OAuth token for you and automatically sets the authorization header parameter with that token. So wyld right?
Hopefully just that simple example above makes you think twice about choosing to not use named credentials… and if it doesn’t, you probably haven’t done many integrations with external systems yet and don’t realize how much time this saves. IT SAVES A TON OF TIME, CONFIGURATION AND CODE! Trust me on this one. I promise I’m not selling you garbage here. It’s worth using 100% of the time.
Get Coding With The Force Merch!!
We now have a redbubble store setup so you can buy cool Coding With The Force merchandise! Please check it out! Every purchase goes to supporting the blog and YouTube channel.
Why On Earth Would We Ever Build Trigger Bypasses?
This is an excellent question and one I wondered myself… until my team and I had to do a monstrous 50,000,000 record load into Salesforce for a deployment, lol. I was stumped… how on earth could I ever pull this off without taking days or weeks to upload that data. We’re not gonna into all the detail behind that monster data load, but we’ll just say turning off the triggers was a part of it. Then we were faced with the, you can’t turn off the system while we do this data load and I was like, fml, how though? As it turns out there is a way! And a really good and simple way if you leverage Custom Settings.
There are a number of other reasons to do this too. A data team that loads data that’s pre-transformed (doesn’t need to go through the trigger) or an integration that auto-transform the data and doesn’t need to be bogged down by a trigger. There are plenty more beyond these as well, but these are the major ones.
What are Custom Settings?
Custom Settings are much like Custom Metadata in that they are typically used in the same way as a config file in another programming language. That being said they are a bit different. Unlike custom metadata, custom settings allow you to change the values of the data you store based on the user that is currently running the code. So each user in your system can have different values for custom metadata records. Pretty nifty, if I do say so myself.
So How Do We Set This Bypass Up?
This is so simple it’s mind boggling, lol. All you need to do is setup a hierarchy custom setting object by going to Setup -> Custom Settings and then create Checkbox (Boolean) fields for each object you have a trigger for that you may want to bypass.
After you’re done setting that bad boi up. Click the “Manage” button at the top of your custom setting so that you can create records for it. After you do that you’re going to be presented with two different “New” buttons on the screen and it’s not super obvious what either of them do, so let me explain. The top “New” button is to make default values for ALL USERS in your org. This is the Default Organization Level Value. The bottom “New” button allows you to make new records that are only relevant to certain Users or Profiles. The bottom “New” button is what we want to click.
After clicking the bottom “New” button you’ll be presented with option to select a, “Location” which is the most confusing label of all time, lol. This just expects you to choose a User or a Profile which will then allow you to have unique values for Users and Profiles for your custom setting! Pretty Kewllllllll. Select the profile or user you would like to bypass your trigger(s) and select the checkboxes for the triggers they should bypass and then hit “Save”.
That’s it, pretty damn simple. Now on to the equally simple trigger code.
The Trigger Code
You might be thinking, oh no code… I’m sorry if you feel that way because code is the most amazing thing since General Tso’s Chicken. However, if you do, no worries, we need four lines of code… yes that’s it. Now before I show you this code, please note, you should be utilizing a trigger framework for your code and that no logic should live in your triggers… but that’s for another day. This is just a simple example, so lets check it out.
trigger Account_Trigger on Account (before insert)
{
//Getting the Process_Switches__c custom setting value that is relevant to our running
//user
Process_Switches__c processSwitches
Process_Switches__c.getInstance(UserInfo.getProfileId());
//If the user can bypass the trigger, return and do not continue the trigger.
if(processSwitches.Account_Process_Bypass__c)
{
return;
}
//Call your trigger handler and run trigger logic
}
Woop, there it is. Pretty simple stuff. If you’re not familiar with Custom Settings and the unique ways to query data from them the whole [Custom Setting Name].getInstance(UserInfo.getProfileId()) might look a little confusing. It’s pretty simple though. It basically gets the custom setting record that is relevant for the running users profile. This makes sure we always get the correct record and only the right people are bypassing the trigger! Pretty kewl huh? And that’s it, yep, that’s really it. Now go enjoy a trigger free world where your data loads go lightning fast.
Get Coding With The Force Merch!!
We now have a redbubble store setup so you can buy cool Coding With The Force merchandise! Please check it out! Every purchase goes to supporting the blog and YouTube channel.
Why Would We Want Our Process Builders to Bypass Our Triggers?
If you didn’t know process builders fire your triggers every single time they make an update to a record or insert a new record. If you have 5 different update actions in your process builders that means you could potentially fire your triggers 5 times in the same process builder execution!! That would absolutely destroy your operation speeds, and if you didn’t know Process Builders are already know to be very poor performance wise (taking up to 40 times longer than flows or triggers to operate). That being said even process builders have their place, especially in admin heavy orgs. So let’s figure out how to make sure they are as performant as they can be.
As a side note: If your process builders rely on your trigger to re-run after they execute… you have a problem and you need to fix it. Process builders should never require a trigger to re-run after it executes.
Setting Up The Super Simple Apex Code To Make This Work
First things first. If you want the code and config for this , you can grab it here on github.
Now let’s get to it! Unfortunately we have to write a little apex code to make this magic work (or fortunately if you love code like me), but don’t worry! It’s very simple. The first this we’re going to make it a small utility class that allows us to pass in the name of a trigger we’d like to bypass.
//The utility class that allows us to determine which triggers we want to bypass
public with sharing class Util_Trigger_Name_Bypass
{
//The set of trigger names that we want to bypass in our trigger.
public static Set<String> bypassedTriggers = new Set<String>();
//Method that allows us to add a trigger that we want to bypass
public static void bypassTrigger(String triggerName)
{
bypassedTriggers.add(triggerName);
}
//Method that allows us to remove a trigger from our bypassed triggers set
public static void removeBypass(String triggerName)
{
bypassedTriggers.remove(triggerName);
}
}
There is one major thing to note about the code above. We utilize the static keyword to declare our variable (and our methods too). If you are not familiar with the concept of static (or class) variables, you should definitely take the time to investigate them more, but I will briefly explain it here. Static variable persistent for your entire execution context. What this means is that our variable’s value will remain the same in the trigger and the process builder (and anything else after or inbetween). This is critical! If it wasn’t a static variable we wouldn’t be able to achieve this.
Now that we have this nice utility class that allows us to put the names of the triggers we would like to bypass. Let’s write a couple more small apex classes with invocable methods that our process builder can call to add the name(s) of our triggers we would like to bypass while our process builder is running.
//Class that you can call from a process builder that allows you to stop a trigger from executing
public with sharing class Util_PB_Trigger_Stop
{
//You can find this invocable apex method in your process builder when you look for
//the "StopTrigger" label in an apex action.
//This method adds trigger names to the utility we made that stores trigger names we
//would like to bypass.
@InvocableMethod(Label = 'StopTrigger' Description='Method allows up to bypass
triggers')
public static void stopTriggers(List<String> triggerNames)
{
Util_Trigger_Name_Bypass.bypassTrigger(triggerNames[0]);
}
}
//Class that you can call from a process builder that allows you to start a trigger again
public with sharing class Util_PB_Trigger_Start
{
//You can find this invocable apex method in your process builder when you look for
//the "StartTrigger" label in an apex action.
//This method removes trigger names from the utility we made that stores trigger names
//we would like to bypass.
@InvocableMethod(Label = 'StartTrigger' Description='Method allows up to restart
triggers')
public static void startTriggers(List<String> triggerNames)
{
Util_Trigger_Name_Bypass.removeBypass(triggerNames[0]);
}
}
As you can see the above apex classes just allow us to add or remove the names of our triggers we want to bypass to our utility class’s bypassedTriggers Set. Noice, very convenient and very simple. The last two things we need to do are update our trigger, so that it looks to our Util_Trigger_Name_Bypass utility class to determine if it should run and create our process builder!. Let’s take a look at the trigger.
//Our Case Trigger. Please use a trigger framework and never put logic in your triggers.
//I created this trigger in this way for demonstration purposes only and to
//simplify this lesson.
trigger Case_Trigger on Case (before update, before insert)
{
//Looking at our utility class to determine if we should run our trigger logic.
if(!Util_Trigger_Name_Bypass.bypassedTriggers.contains('Case_Trigger'))
{
Case_Trigger_Handler.beforeUpdate(trigger.new);
Case_Trigger_Handler.beforeInsert(trigger.new);
}
}
As you can see from the above trigger, before we execute the logic for our trigger we first check to determine whether or not our utility class’s bypassedTriggers set contains the name of our case trigger. If it does, then we do not execute our logic.
Setting Up The Process Builder
You can setup your process builder to bypass your triggers in two different ways. You can have your process builder shut off the trigger before it runs any operations or you can have it shut off the trigger just within the immediate action blocks that actually update or insert records. I would personally suggest you just turn it off for the entire length of the process builder because it’s more performant that way, so that’s what I’m going to show you below. If you would rather do it the other way, the video linked above explains it in detail.
As you can see from the above pictures this is super simple! We just create two nodes, one to stop the trigger at the beginning of the process builder and one to re-start the trigger at the end of the process builder. Both of those nodes have apex actions within their immediate actions that call the StopTrigger and StartTrigger Invocable apex methods respectively and pass it the name of our trigger we want to disable (in our case the Case_Trigger). Then you place any update or insert actions between those two nodes and you’re good to go! No more trigger logic run while your process builders execute! Wooottttttttt!!!!!!!!! Enjoy that massive boost in process time. The only next steps you have are to eliminate your process builders entirely, lol, because they are just garbage.
Moderately Important Note: Make sure you “Evaluate Next Criteria” in the “Specify What Happens After Evaluating This Criteria” node.
Get Coding With The Force Merch!!
We now have a redbubble store setup so you can buy cool Coding With The Force merchandise! Please check it out! Every purchase goes to supporting the blog and YouTube channel.
How to Render Elements of a Custom Community Password Reset and/or Welcome Email Conditionally
Alllllrighhtttttttt, so if you didn’t read the first blog post, you might get a bit lost, so be sure to check that out here.
If you have already read it, let’s figure out first why the hell you would ever want to do this conditional rendering magic. It’s because of the following:
1) You can only associate one password reset email and/or welcome email to your community (This is especially important for password reset emails as we’ll see in a bit).
2) If you need different user groups to receive different things in their welcome or password reset emails, you need to be able to conditionally render elements based on who the email is being sent to.
So now that we know why we would do this, let’s figure out how we would go about doing this.
<!--This is the visualforce component-->
<apex:component id="ToightComPassReset" access="global" controller="ToightComPassResetController">
<apex:attribute name="contactIdPassed" description="Contact id passed from email
template" type="Id" assignTo="{!contactIdPassedCtrl}"/>
<p>Hi bro wut upppppppppppppp</p>
<div style="{!IF(ProfileName='Customer Community Plus Login User', 'display:block',
'display:none')}">
<a href="{!$Network.NetworkUrlForUserEmails}">Click here to reset your
password</a>
</div>
</apex:component>
//This is the visualforce component controller
public with sharing class ToightComPassResetController
{
public Id contactIdPassedCtrl{get; set;}
public String getProfileName()
{
String profileName = '';
List<User> usersFromContact = [SELECT Profile.Name FROM User WHERE ContactId =
:contactIdPassedCtrl LIMIT 1];
if(!usersFromContact.isEmpty())
{
profileName = usersFromContact[0].Profile.Name;
}
return profileName;
}
}
So, obviously to a seasoned developer the code above is not super complicated but if you’re not familiar with it or why I wrote the component the way I did, let me explain it a bit. Here are some key pieces of the vf component:
1) Your component must be declared as access= “global” or else it will not be visible to your email template.
2) The component is declared with an <apex:attribute> tag, this tag allows you to send data to your visualforce component from the email template and pass that data to your apex controller. In our case we will be sending the contact Id from the email template and assigning it to the contactIdPassedCtrl variable in the apex controller.
3) We conditionally render a div on the page using an IF condition instead of just using a pageblock. This is because you can’t utilize pageblocks in email templates, you have to use normal html elements.
4) This conditional rendering might seem confusing, “{!IF(ProfileName=’Customer Community Plus Login User’, ‘display:block’,’display:none’)}” but it’s actually fairly simple when explained, so let me do that. Basically what it’s saying is, if the getProfileName method in our apex controller returns a value of “Customer Community Plus Login User” display our div, otherwise don’t display it.
5) If you didn’t know, in Visualforce, if your apex controllers method starts with the word get, you can reference it without the word get in the vf page/component. More examples here.
Referencing our Visualforce Component in the Email Template
Alright so now that we have our vf component and our apex controller built, let’s check out how to reference that component in our email template!
Pretty simple right? Not a lot to it. To reference the vf component we just use the component tag “<c:ToightComPassReset>” which is just <c: followed by the name of the vf component you made and we use the “contactIdPassed” parameter to pass our contacts id to the component. If you don’t remember our recipient type is equal to contact so the “recipient.Id” merge variable references the contact id. Additionally the contactIdPassed is the name of the <apex:attribute> we declared in our vf component.
Now for the frustrating truth… Welcome emails do not work with conditional rendering
You might be thinking… then why did you just waste my time. Please don’t worry, not all hope is lost. Yes, unfortunately when you use the OOTB welcome email setup for communities they for some reason do not respect the conditional rendering (at least when looking at profiles or permission sets)… it is infuriating, I tried a million different ways and I almost gave up all hope, but where there’s a will, there’s a hacky Salesforce solution, so let me walk you through it.
Thankfully, reset password emails and emails sent in the after portion of a user trigger respect conditional rendering just fine! So let’s figure out how to leverage that knowledge. Before setting up the trigger though let’s do a little more prep work.
Next build a custom vf template welcome email if you want one that differs from the password reset email.
Make sure your password reset email is still selected for the Forgot Password and Change Password email options in your community’s admin email tab.
And now… let’s make a User trigger.
Creating a User Trigger to send out community password reset and welcome emails
Yep, this is it, we’re finally on the last step. To finish this and make custom password reset and welcome emails work for your communities.
Below is some example code showing you how to do this. Fair disclaimer here, this is not how you should setup a trigger ever! You should be using a trigger framework like this one and leveraging it, but I wanted to keep this simple for those of you out there who are less familiar with triggers. Please DO NOT PUT THIS CODE IN YOUR ORG WITHOUT REWRITING IT TO BE MORE SPECIFIC FOR WHEN TO SEND OUT EMAILS!! You can also view the code on github here.
//This is our User trigger
trigger UserTrigger on User (after insert)
{
if(trigger.isAfter && trigger.isInsert)
{
CommunityEmailManager.processEmails(trigger.new);
}
}
//This is our helper class to send out emails
public with sharing class CommunityEmailManager
{
private static final String PROFILE_NAME = 'Customer Community Plus Login User';
public static void processEmails(List<User> userList)
{
Set<Id> profIds = new Set<Id>();
for(User usr: userList)
{
profIds.add(usr.ProfileId);
}
Map<Id, Profile> profilesFoundMap = new Map<Id, Profile>([SELECT Name FROM
Profile WHERE Id IN: profIds]);
List<Messaging.SingleEmailMessage> welcomeEmails = new
List<Messaging.SingleEmailMessage>();
List<EmailTemplate> welcomeEmailTemplates = [SELECT Id FROM EmailTemplate
WHERE DeveloperName = 'Taco_Bueno' LIMIT 1];
for(User usr: userList)
{
if(profilesFoundMap.get(usr.ProfileId).Name == PROFILE_NAME)
{
//Sending out our password reset emails
System.resetPassword(usr.Id, true);
}
//Setting up our welcome email to send by rendering our vf email
//template
Messaging.SingleEmailMessage welcomeEmailMessage =
Messaging.renderStoredEmailTemplate(welcomeEmailTemplates[0].Id,
usr.ContactId, null);
String [] toAddresses = new String[]{usr.Email};
welcomeEmailMessage.setToAddresses(toAddresses);
welcomeEmails.add(welcomeEmailMessage);
}
if(!welcomeEmails.isEmpty())
{
//Sending out our custom welcome emails
Messaging.sendEmail(welcomeEmails);
}
}
}
So again this code isn’t super complex, but let me explain what’s happening in the Community email manager just a bit.
1) Because we cannot get object relationship fields in triggers, if you are sending emails based on profiles we need to grab the ids of our new users profiles and query the profiles object to create a map of profiles so we can figure out the names of our users assigned profiles. Unfortunately we cannot use the Profile.Name relationship field on the User object like we did in our VF component controller.
2) If you created a custom welcome email that is separate from the password reset email, you need to query to find its template via the EmailTemplate object, we need the Id of the template to render it for our email we send out later in the code.
3) The System.resetPassword() method is what is sending out the reset password emails for our users. This will send out reset password emails for all communities they are members of (so be careful and make sure you only send them out when necessary).
4) The Messaging.renderStoredEmailTemplate method takes three parameters, the Id of the email template you intend to render, the Id of the recipientType and the Id of the RelatedToType for your template. This method works the best for rendering visualforce email templates.
5) We add our outbound emails to a list of single email messages. This is important because while we can send thousands of emails at one time, we can only call the Messaging.sendEmail() method up to ten times in the same context. So we want to send that method a giant list of emails instead of one email at a time.
Now, if you test out your emails you should have conditional rendering working in your templates, password reset links in your super customized password reset emails and now you can do whatever you can dream of with those emails. We did it!!!
Get Coding With The Force Merch!!
We now have a redbubble store setup so you can buy cool Coding With The Force merchandise! Please check it out! Every purchase goes to supporting the blog and YouTube channel.
Why Would We Need to Create Custom Welcome and Password Reset Emails?
There are a handful of reasons that you would need to create custom password reset and welcome emails for your Salesforce Communities. The most common reasons are the following:
1) The out of the box (OOTB) custom password reset and welcome emails are just bland and boring. They are regular text templates with not a lot to them.
2) There are multiple users types in your community. Some users need to see different things in their welcome and password reset emails, so we need to render different sections of the emails for different user types.
3) Some users sign in via Single Sign On (SSO) and don’t need a password reset email, but some users aren’t allowed to use SSO and do need to sign on via the normal Salesforce community login page.
All of these are legitimate and relatively common business cases for customizing your password reset and welcome emails, that being said Salesforce doesn’t make this process easy or document it well, so let’s dive in to how we can achieve these custom emails.
To create a new vf email template, do the following:
1) Go to Setup -> Classic Email Templates and click the “New Template” button. 2) Select the “Visualforce” template type 3) Fill out the “Email Template Information” section with whatever you’d like. 4) In the “Visualforce Template Attributes section, make the “Recipient Type” Contact and the “Related To Type” Network 5) Click the “Save” button
There is a ton of conflicting information on the internet about what to make the Recipient Type and Related To Type for these email templates. CONTACT AND NETWORK SHOULD ALWAYS BE WHAT YOU USE IN THIS INSTANCE! You might be like, “But why bro? Why that matter at all?”. For these password reset and welcome emails for community members these objects seems to work best without any problems (I’ve tested tons of combinations). You get merge field issues when you utilize the User object instead of the Contact object for recipient and you get the most additional useful information from the Network object (which is the object that stores your community information in SF). Feel free to do more investigation yourself but I have wasted days of my life on this, lol… it wasn’t super fun.
The Visualforce Email Template Code and The Magical Global Network Merge Field
After you’ve created/saved your visualforce email template, press the “Edit Template” button. You should see something like the code below:
<messaging:emailTemplate subject="wow" recipientType="Contact" relatedToType="Network">
<messaging:plainTextEmailBody >
Congratulations!
This is your new Visualforce Email Template.
</messaging:plainTextEmailBody>
</messaging:emailTemplate>
You should go on ahead and change it to something like this (the words inside the paragraph tag can be anything):
<messaging:emailTemplate subject="wow" recipientType="Contact" relatedToType="Network">
<messaging:htmlEmailBody >
<p>Hi there welcome to the community</p>
{!$Network.NetworkUrlForUserEmails}
</messaging:htmlEmailBody>
</messaging:emailTemplate>
2) I added the paragraph tag and the most magical merge field in the system (at least for this blog post) !$Network.NetworkURLForUserEmails
Let me tell you… Several years ago, when I first attempted this, I googled a ton of different ways before I finally found this merge field. This network merge field normally gives you the url for the login page of the community, but if this is in a welcome email or a reset password email for the community it will create a link for the reset password page! This is the key to making our custom password reset emails… but there’s even more to consider with this, unfortunately.
How to Test Your New Custom Welcome and/or Password Reset Email
You might be thinking, “Yes! This Network merge field solves all my problems”, but there’s one more thing you need to take into consideration (at least) and that’s how to test this new custom email you’ve made. If you try to use the, “Send Test and Verify Merge Fields” button to test this email, you’ll notice that it doesn’t work… the password reset link just won’t send… great. So what do you do?
To test this email we need to do the following:
1) Go back to your community and override the password reset emails in the Workspaces Emails tab.
2) Create a contact that has (at least) a first name, last name, email and account associated to them.
4) Make sure the community user for the contact has a profile or permission set that makes them a member of the community. Also make sure they have an email associated to their user that you have access to.
5) Grab the Id for the user you just created from the URL of your user record
8) Paste the code below into the Execute Anonymous Window and then click the “Execute” button
System.resetPassword('[Your user Id you copied above]', true);
After running that System.resetPassword(userId, sendEmail) method in the execute anonymous window you should receive an email with a password reset link inside it! Wooooooooooooooooo!!! We did it!! We got an email setup that we can heavily customize that we can also get a password reset email in! Depending on your needs though… this may not be enough. There are a few more caveats to get through if you need different things rendered for different community member types, etc.
Getting Technical With It
If you need to segment out your emails and/or render things conditionally for different users, move on to the next blog post here.
We go over how to build Visualforce Components to conditionally render elements of your email based on the user we’re sending the email to, the extremely interesting problem doing that with Welcome emails and how to setup a trigger on the User object to determine who to send different emails to.
Get Coding With The Force Merch!!
We now have a redbubble store setup so you can buy cool Coding With The Force merchandise! Please check it out! Every purchase goes to supporting the blog and YouTube channel.
IDE stands for Integrated Development Environment. Its primary purpose is to make your life as a developer considerably easier by doing things like:
1) Syntax Highlighting 2) Auto-completing functions names, field names, object names, etc. 3) Integrating git easily 4) Improving debugging functionality 5) Putting your command line in the same place you develop. 6) Tons and tons of other things
It is well worth your time to invest an hour or two to figure out how to use an IDE to improve your productivity as a developer.
Back when I started developing on this platform the only IDE’s we had was the Force.com IDE in Eclipse and the Dev Console… if you really count it. Today there are five IDE’s to choose from and I’m gonna walk you through how to install and configure my personal favorite, Illuminated Cloud 2.
Before I get started here are a list of your IDE options and their prices:
I struck out the last two because you really shouldn’t ever use them even though they are technically available options.
I have tried out all of them and my preference is IntelliJ/Illuminated Cloud 2 and that’s because between the incredible power of the widely used and extremely popular IntelliJ IDE and the impeccable work Scott Wells has put into Illuminated Cloud 2 to help it leverage all of those IntelliJ features for SF development, it’s borderline impossible to top it. It is the most point and click/easy to use of them all and it does not suffer because of it.
How to Setup IntelliJ and Illuminated Cloud 2
Here are the steps necessary to setup and be able to use Illuminated Cloud 2 for Salesforce development in IntelliJ.
3) After the JDK and IntelliJ have been installed, open IntelliJ and go to File -> Settings -> Plugins, click the Marketplace tab at the top and search for Illuminated Cloud
4) Click the install button to install Illuminated Cloud 2 (Do not install the original Illuminated Cloud option, it is outdated).
5) After Illuminated Cloud is done installing and IntelliJ restarts, start creating a new IntelliJ project. File -> New -> Project -> Illuminated Cloud.
6) Click the “New Connection” button in the top right (the pencil icon). It will pop-up a new Connections modal. In that new modal click the “Create Connection” icon in the top left (the plug icon).
7) Enter the information it requests: Organization type, username, password, security token (if you don’t know what the security token is my video above explains where to find it in SF) and then click the “OK” button in the bottom right.
8) If you entered in the right connection information it will give you a confirmation message that your information was valid and it will connect to your org and give you a preview of the metadata you can pull from your org.
9) Check the checkboxes next to the metadata you would like to pull for your org and then hit the next button.
10) After hitting the next button, name your project and module whatever you’d like to name them and then click the “Finish” button!
11) That’s it you did it! You can do SF dev work in IntelliJ!
Useful Illuminated Cloud 2/IntelliJ Hotkeys
There are a ton of useful hotkeys for both IntelliJ and Illuminated Cloud 2. You can find all the Illuminated Cloud 2 hotkeys here and all of the IntelliJ hotkeys here.
Here is my shortened list of hotkeys I use every single day:
1) Reformat Code: Crtl + Shift + L 2) Get more information about a method, object, field, etc: Ctrl + Q 3) Search your entire project: Ctrl + Shift + F 4) Go to external SF Documentation: Shift + F1 5) Go to highlighted Apex Class: Ctrl + N 6) Go to highlighted component: Ctrl + Shift + N
There are tons and tons more that are super useful, so be sure to check them all out!
Get Coding With The Force Merch!!
We now have a redbubble store setup so you can buy cool Coding With The Force merchandise! Please check it out! Every purchase goes to supporting the blog and YouTube channel.
Have you ever wondered, “How do I effectively schedule an apex class to run every single minute of the day?” or maybe every hour or second (please don’t schedule anything every second, lol). Well there’s a great way to do it, by having your scheduled apex class reschedule itself! This method also significantly cuts down on the jobs you have to cancel to actually make any updates to your scheduled class as well. Say for instance you did schedule the class to run once a minute. That equates to 1440 scheduled jobs!! That’s a nightmare… with this method, you’ll only have one scheduled job but it will still run every minute of the day. Yay!
So let’s just get down to it… how does this magic work? It’s actually pretty simple. In your scheduled class you just find your currently running scheduled job, abort it and then reschedule it! Let’s check out the code below or on Github.
The Code
/**
* @description An example of a continually rescheduling job.
* @author Matt Gerry
* @date 9/5/2020
*/
public with sharing class Repeating_Scheduler_Example implements Schedulable
{
private final String JOB_NAME = 'Repeating Job';
private final Integer ONE_MINUTE = 1;
/**
* @description The execute method fires each time the scheduler is run. Unless there is a
constructor, this is always the first method to fire.
* @param cont Schedulable context instantiated by the Schedulable implementation
* @example System.schedule(JOB_NAME, cronExpression, new Repeating_Scheduler_Example());
*/
public void execute(SchedulableContext cont)
{
new Repeating_Scheduler_Case_Insert().insertCase();
findAndAbortJob(cont);
}
/**
* @description Aborts the existing scheduled job. Then calls rescheduleJob to
reschedule this job.
* @param cont Schedulable context instantiated by the Schedulable implementation
* @example finaAndAbortJob(cont);
*/
private void findAndAbortJob(SchedulableContext cont)
{
if (cont == null)
{
return;
}
//Need to query CronJobDetail to find our currently active scheduled job
List<CronJobDetail> cronDetail = [SELECT Id FROM CronJobDetail WHERE Name=
:JOB_NAME LIMIT 1];
if (cronDetail.isEmpty())
{
return;
}
//Need to find the corresponding cron trigger to be able to abort the
//scheduled job
List<CronTrigger> cronTriggers = [SELECT Id FROM CronTrigger WHERE
CronJobDetailId = :cronDetail[0].Id];
if(cronTriggers.isEmpty())
{
return;
}
try
{
//Aborts the job current setup for this scheduled class
System.abortJob(cronTriggers[0].Id);
rescheduleJob();
}
catch (Exception e)
{
System.debug('This was the error ::: ' + e.getMessage());
}
}
/**
* @description Reschedules this job for one minute in the future.
* @example rescheduleJob();
*/
private void rescheduleJob()
{
Datetime sysTime = System.now().addMinutes(ONE_MINUTE);
String cronExpression = '' + sysTime.second() + ' ' + sysTime.minute() + ' ' +
sysTime.hour() + ' ' + sysTime.day() + ' ' + sysTime.month() + ' ? ' +
sysTime.year();
System.schedule(JOB_NAME, cronExpression, new Repeating_Scheduler_Example());
}
}
Aborting The Job
So as you can see from the above code, all we need to do is take the name of the job and query the CronJobDetail object to find the corresponding Cron Job for our scheduled apex and then we query the CronTrigger object to get that id so we can abort our scheduled apex’s next run. After getting the CronTrigger record Id we then utilize the System.abort method to abort our scheduled apex so that we can reschedule it.
Rescheduling The Job
After we abort the job we simply utilize the System.Schedule method to reschedule our class for a time in the future. In this code we just set it to one minute in the future via a variable, but I would suggest utilizing a custom metadata type to do this as it gives you the most flexibility.
Get Coding With The Force Merch!!
We now have a redbubble store setup so you can buy cool Coding With The Force merchandise! Please check it out! Every purchase goes to supporting the blog and YouTube channel.