Nov 30, 2015

Salesforce Triggers, Workflow, and Process Builder






The Question:


How is it possible for triggers to fire three times on a single save of a record? There are many reasons this can happen in the Salesforce1 platform. Our problem had to do with Workflow and Process Builder. We were expecting only 1 extra trigger to fire because we were using workflow field updates and process builder field updates, figuring that the additional DML would be grouped at the end and fire one more time. But instead we found 2 extra triggers fired.


The Problem:


A DML (Data Manipulation Language) operation is happening and it causes the trigger to fire. Then, the workflow rule executes and that causes the trigger to fire a 2nd time. Then, the Process Builder flow fires and inside the Process Builder flow, the trigger fires a 3rd time.


When the Process Builder flow is deactivated, the trigger fires twice.  When the Process Builder flow is left active and all the workflow rules are deactivated, the trigger fires twice, as well.




The Solution:


The answer is to set a static variable during the first execution, and then reference this variable to determine whether or not subsequent code should be executed. But be careful in the unit tests; after each DML in unit test, the flag will have to be set to false again if you intend to try insert, then update, then update etc., since each unit test is in the same context and considered the "same execution."


Here is how the trigger starts out:








Further Exploration:


Many might have known the ‘before and after executions’ in the order of executions, but perhaps hadn’t seen that the Process Builder causes a third run.  The question arises, as to where the Process Builder runs in the order? A review of the Salesforce Developers Force.com Apex Developer’s Guide: Triggers and Workflow, does not list it in the order of execution running as it did in the example above.



The Process Builder can be set up to cause a re-execution. So one might still wonder if the Process Builder re-triggers from the top of the execution, entirely? The thinking of our team at CRM Science is that it is both Workflow, and Process Builder. One might have imagined that Salesforce would combine Workflow, and Process Builder, into the same steps so they don’t run trigger so much. On "busier" objects or objects prone to bulk inserts/updates through data loads, you may find yourself avoiding introducing processes into the mix. If you have the capability to do so, stick with triggers; at least, for now.


Considerations For Large Salesforce Orgs

In really large Salesforce Orgs triggers on core CRM objects can become a bane of an admin or developer’s existence if the last group in charge of the org didn’t control usage.  Stick to as few triggers as possible per object (ideal is one), as little logic as possible within the trigger bodies, and utilize a common trigger handler method for further processing. For developer friendly orgs, consider the creation of a control system, like a Custom setting, to easily enable and disable home-brewed triggers in your Production environment.
Have A Salesforce Puzzle? Let's Solve It Together! 
Contact Us Here.




Sep 15, 2015

Stop Drop & Rollback -- How to handle errors properly in Apex/Salesforce with Try, Catch, Rollback Best Practices

Visit our website




Smokey Says - Care will prevent 9 out of 10 Apex errors!
There are some assumptions that we know about when coding in Salesforce in regards to protecting the developer from saving partial-processed data in Salesforce.

- Any exceptions that happen in code(within the same entire execution) will roll back the entire execution so that all database changes leading up to the failure will not be committed to the database.  This is true for triggered code, page controllers, asynchronous code, etc.  This was a GREAT thing as I started developing in Salesforce and really protected the data for the customers.

- The above is only true if: 1. You are not using try/catch blocks around DML operations(which results in undesirable errors on top of standard pages or white-screen error pages from custom pages) 2. Or you are using try/catch blocks and are properly handling the error inside the 'catch'.

There are many uses of try/catch which I won't cover here but you can check that out here.

My Experience

The more custom work I did the more I realized that I was using try/catch all over the place but didn't immediately understand the dangerous implications of using it.  I've talked about this topic many times with other developers, explaining my experience, and it can be a complex one to discuss but I'll try to lay out some hypothetical situations.

Situations

  1. You want to use try/catch in a page controller so that you can show a friendly error on the screen for the user.  There are 2 DML operations in the 'button click' action, and say the error happens on the second DML.  So you tell the user there is an issue by adding a pagemessage.  Did you do anything to undo the 1st DML which was a success? Salesforce will not roll-back that DML for you because you've essentially "caught" the error that would have done that.  Result: Bad data. You need to roll-back.
  2. You've got a trigger on Case that will roll-up some custom information to the Account.  This important logic will keep the data in-check.  But sometimes there is an issue when you run the DML Update to the accounts, so you wrap the DML in a try/catch and perform a system.debug to figure things out a bit better.  You've deployed things like this to production since it is very rare.  By "catching" this error and the only handling you've done is a debug, you have told Salesforce not to roll-back the changes to the original Cases that fired the trigger.  You'll end up with Cases(newer changes) out of sync with Account(failed update) in your database.  The solution is that you need to attach a ".adderror()" to the appropriate Case records in the trigger which will tell salesforce to roll-back changes and will show your custom more descriptive error to the user(or to the calling code / external system). Result: Bad data. You need to .addError

Code Examples - VF Controller


VF Controller Good Example no try/catch - Standard exception handling, SF handles database protection KEY: Do nothing extra (Good)

VF Controller Bad Example with try/catch - Account will insert without the case
Since we are using try/catch below, we are able to show the user a nicer error message with the ApexPages.addMessage method. BUT, we are now taking over the standard salesforce pattern of "error and rollback". And we are forgetting to rollback ourselves.


VF Controller Good Example with try/catch - If Case fails, Account insert will rollback KEY: Using Database Rollback (Best Practice)


Code Examples - Trigger

Trigger Good Example no try/catch - Standard exception handling, SF handles database protection KEY: Do nothing extra (Good)


Trigger Bad example with try/catch - Account update could fail but we didn't stop the Cases from being inserted


Trigger Good example with try/catch - If Account update fails, we flag the Cases with an error which will show to user and prevent the Case inserts KEY: Use .addError() method (Best Practice)

Other Tips

- When using the generic exception class, it will catch any type of error besides for limits and some other situations. Be careful not to put too much inside the same Try block as it'll be more difficult to figure out what caused the error. Best practice would be use specific exception classes like dmlexception and only put a single DML in that try block.

- Make sure to test your catch blocks.  In your manual tests you can configure a dummy "requirement" on an object or a validation rule you know will fail, or leave out a required field. Then attempt the custom button, standard button, whatever it is that starts the code which should fail and see how your catch block operates.  For unit tests this could be more difficult but you could employ some special logic to conditionally fill in data or fail to fill in data in your code.  Say your controller would be looking for "Unit Test *** Fail DML Required Field" it could know to purposely clear a field on a record before the DML which would then fire your catch block.  Or you have a Unique field setup in an object and let your unit test try to insert 2 records with the same values in that field.  There's many other things you could do, up to you.

Dreamforce '15 Session: Enhanced Web Service Testing: A Better Mock Structure

Session Title: Enhanced Web Service Testing: A Better Mock Structure

When: Tuesday, 9/15/15 at 5:30 PM
Where: Moscone West - 2007

Details
Salesforce provides an interface for testing callouts named HttpCalloutMock used to cover remote callouts. While adequate for simple callouts, in the real world you often need something more flexible, as in the case of multiple and varying responses from the same or varying endpoints. More precise testing and coverage can be obtained by extending the standard interface. Join us as we demonstrate a solution to use to enable the flexibility required for complex integration and synchronization apps.

Deck:  http://bit.ly/df15_kirk_deck
Unmanaged Package:  http://bit.ly/df15_kirk_pack_v1_1
Original Blog Post:  http://blog.crmscience.com/2014/12/test-coverage-pattern-for-multi-callout.html

Sep 8, 2015

Lab Coat Challenges: Challenge #5 Now Available


Challenge 5: Magic 8 Ball

Hey developers (and budding developers)!

Dreamforce is next week!  Who saw that coming?  If you follow us on Twitter (@crmscience), you probably did. #CalendarCube.

Being next week, you might be strategizing when you're going to get your selfie in with SaaSy.  With this week's challenge, we wanted to give you a way to wake up in the morning and definitely have an answer for "Will I see SaaSy today?"
 
Objective
You'll be creating a magic 8 ball like method that returns a string.  This magic 8 ball, though, only answers one question... "Will I see SaaSy today?"  You know, because a Dreamforce without a SaaSy selfie is like eating a cupcake without icing.

Within the method, determine how to randomly select return one of the valid answers.

Click here for the full details, rules, and starter code!























Sep 7, 2015

Lab Coat Coat Challenges: Challenge #3 Responses!



Great round of submissions for this Lab Coat Challenge!

It's interesting to see how everyone had a similar approach to resolving the problem and used different tools to get there. Some were able to create concise solutions that made use of system methods while others ended up replicating the same work or something very similar. Great example of where it pays to know (or, minimally know they exist) some of the more rarely used methods in the documentation.

Thanks to everyone who has participated so far and for those that are checking these answers out now and think they can do better!  Keep the submissions coming and we hope you're enjoying these challenges!

Link:  Lab Coat Challenges

Starter Code



Asserts for all code




@PramForce




@melmoussaoui




@DeborahOrth




@DouglasCAyers




@@scottpelak




@MichaelWelburn




@venky_mass




@@SF_Tidbits






@anonymous






@nickforce




@CloudAnatomy




@michaelbsalty













Sep 1, 2015

Lab Coat Challenges: Challenge #4 Now Available

Challenge 4: Get Crackin'

Hey developers (and budding developers)!

Think you're pretty saavy when it comes Salesforce?  Demonstrate your mastery of the platform and earn the best badge possible - an honorary CRM Science lab coat!

The last challenge had you thinking with a particular mindset.  This week is a bit of a continuation of that.

Clue
k == a

Objective
Programmatically determine how k relates to a and use that knowledge to decrypt the following string:

Click here for the string!


















Aug 25, 2015

Lab Coat Coat Challenges: Challenge #2 Responses!


Responses are in!


Just like our first challenge, the second had a lot of great submissions. A few common approaches early in the week and a few revisions later after we issued a "Can you do it in a single FOR loop" sub-challenge.

Again - If you haven't had a chance to submit your answer for this challenge OR you think you can improve upon the answers below, please do!


@EricFishmanSF



@melmoussaoui



@DouglasCAyers



Anonymous



@tet3



@debdeepSFDC



@DeborahOrth



@kirkevonphilly








Aug 23, 2015

Lab Coat Challenges: Challenge #3 Now Available


Challenge 3: As Easy as A to B

Hey developers (and budding developers)!

Think you're pretty saavy when it comes Salesforce?  Demonstrate your mastery of the platform and earn the best badge possible - an honorary CRM Science lab coat!

It's back to school already for a lot of young developers out there.  We though this would help them recall some of that knowledge that might have been lost over the summer. 

A... B... shoot, what comes next?

This week's challenge is all about finding the easiest way to increment characters.  How do you increment a string that is set to "A" to "B?"  How about "S" to "T" and so on?

If only if it were as simple as "A" + 1.  Or is it?

In the sample code, you'll be providing the body of a method that accepts two parameters:
  • Letter - a string of a single letter that you'll be incrementing
  • Step - an integer to control how far many steps the starting letter should be shifted.
Up to the challenge?  Review the rules, full details and starter code here!






Aug 19, 2015

Lab Coat Coat Challenges: Challenge #1 Responses!


Responses are in for our first Lab Coat Challenge!

We had some great responses over the last week from several Salesforce devs!  If you haven't had a chance to submit your answer for this challenge OR you think you can improve upon the answers below, please do!




While all technically were valid answers, submissions generally fell into a few camps; those with structure that could be used and extended beyond the example strings and collections provided, those that would only work with the examples given, and those just being..."slick."  We'll call it "slick" and leave the interpretation to you...

Early in the week, no two answers were the same.  By the end of the week, we had several that made use of the list.addAll() method.  Others techniques included various ways of pre-populating lists and even various string manipulations.


All code started with the following...



All code was verified using...



So let's take a look at some of the responses!

Note:  Some code might have been modified up for readability.

Anonymous



Anonymous



@DouglasCAyers



Anonymous



@nitingupta9927



Dan Kelner



@EricFishmanSF



@debdeepsfdc



CRM Science Responses

@kirkevonphilly

When we started preparing these challenges, I wanted to be sure to be able to provide an answer for each. So how did I approach it? Dynamically, of course!



@mikekatulka



Tom Miller







Aug 16, 2015

Lab Coat Challenges: Challenge #2 Now Available


Challenge 2: Reversing Text

Hey developers (and budding developers)!

Think you're pretty saavy when it comes Salesforce?  Demonstrate your mastery of the platform and earn the best badge possible - an honorary CRM Science lab coat!

Challenge #2 is a simple task!  Turn "eeS uoy ta !ecrofmaerD" into "See you at Dreamforce!"  See what we did there?   How few statements do you need?

Up to the challenge?  Review the rules, full details and starter code here!





Aug 7, 2015

Lab Coat Challenges: Challenge #1 is Up!

Visit our website


Introducing the CRM Science Lab Coat Challenges!




Hey developers!

Think you're pretty saavy when it comes Salesforce?  Demonstrate your mastery of the platform and earn the best badge possible - an honorary CRM Science lab coat!

Challenge #1 is all about working with collections and doing so as efficiently as possible.  The gist is you have a few strings, few lists of strings, few sets of strings, and it's up to you to merge them all down into a single list of strings, using as little code as possible.

Up to the challenge?  Get the full details here!








Jun 27, 2015

How to Abort a Scheduled / Queued Apex Job by Name

https://www.crmscience.com/lab-coat-lessons

For the advanced salesforce developers out there.... in the past (before Winter 14 release) there was no way to query for a Scheduled, Future, or Batch job by the name that was given to it. You had to track the ID of the job as the job was being created and store this into a custom object or setting for future reference.

Thanks to a feature from Winter 14 which stemmed from this idea, you can easily query the CronTrigger object filtered by the job name.  Remember to increase your API version in your class if this does not work.

Now we can query for the apex job by name and perform a system.abortjob with confidence that we have the correct job.

Here is a nice block of code that can be used in your application or something to keep handy for an Execute Anyonymous situation.



Jun 9, 2015

This change set requires the "##.#" or later platform version

Overview
It's that time of the year again (one of three times, actually), where you might be attempting to make some fixes in a sandbox that has already been upgraded to the next release and uploading a Change Set from that org to Production where the next release hasn't been applied yet.

Error
This change set requires the "##.#" or later platform version

Scenario
  • Sandbox 1: Summer '15
  • Production: Spring '15

Resolution
By chance, did you get to this point by following a normal deployment pattern? You know, where you deploy from a developer sandbox to a full sandbox and are now ready to deploy to Production? 

Chances are, the full sandbox you deployed to was also upgraded to the next release. You probably already know that upon upload, a Change Set's components are locked down. But did you also know that the API version of that Change Set is set and locked based on the target org's API?




This means that when you uploaded from your developer sandbox to the full sandbox, the Change Set was set to the latest API version and is now locked to it. When you attempt to upload this same Change Set to production, you get the "This change set requires..." error message.

Out of luck? Nope! Just "Clone" the Change Set and re-upload.



When you create a new Change Set by cloning, you're creating a new instance of the Change Set with all the original components and is unlocked so new components can be added.  At this point, the API number has yet to be set as well.

This time, don't upload to a sandbox first; upload it directly to Production so the Production org's API number is set on the Change Set and the upload is allowed.



Jun 8, 2015

User Level Visualforce UI Control w/ Custom Permissions

Overview

As you are developing a Visualforce interface for Salesforce.com users to interact with, you may find that certain form elements (panels, links/buttons, etc) may or should not apply to certain users.  Standard Salesforce user control can prevent users access to a specific page, objects, tabs, or other larger components without allowing much flexibility for the occasional granularity you need.

Sample Scenario

The objective below is to develop a page which offers four command buttons to perform four different actions (Purchase Media, Create Media, Borrow Media, and Rate Media) in a library environment.  In this library environment, there are three different groupings of users (listed in order of privilege); those will complete and full access, librarians, and borrowers.  Full access will be able to perform all actions, librarians can do all but purchase media, and borrows can only borrow and review media.

Approaches


  • User Object Custom Fields:  You could create boolean toggles/checkboxes or minimally a multi-select picklist to allow org Admins to designate access on a per user level.  Downsides are that you're creating a field(s) and it leaves room for admin error (what was it... librarians can purchase or not?).  There's also the cost of querying for these fields via SOQL against the context's execution.  The fields could be included in a package, but would require post-installation configuration (maybe a post-install script to default all).
  • Custom Settings:  You could also create a Custom Setting of the hierarchy type, but still room for admin error.  On the pro-side, Custom Settings are cached and easily accessible via system methods, so it won't count against your SOQL queries.  Can also be included in a package and require the same post-install configuration or defaulting through a post-install script.
  • Custom Permissions:  Depending on your usage, these may or may not count against your SOQL limits.  Management is much easier as you can group individual permissions into a larger Permission Set and then apply the Permission Set(s) to a user.  Now all an Admin has to do is remember which Permission Set to apply to user(s).  Like the other two, can also be included in a package.  They also have the unique benefit in that they can be used to provide custom permissions to users authenticating in Connected App.

Custom Permissions 


We'll be checking out Custom Permission creation, assignment, and usage in the samples below.  To do so, we'll build a Visualforce page with four buttons, one for each possible permission, as well as show two page block sections that show which permissions the current user has.  One page block section will use the $Permission global variable to make that determination straight from Visualforce without a controller (see "Global Variable Way" below) and the other page block section will use Apex to determine applied permissions (see "sObject/SOQL Way").

Here's the end result:


Before we get to the good stuff, let's see how to create the Custom Permissions and get them applied to a User first...

Creating Custom Permissions

  1. Navigate to Setup --> Build --> Develop --> Custom Permissions


  2. Click on the "New" button and provide the various details about your Custom Setting.  The thing to remember here is it's up to you to determine what this "permission" stands for - at the end of the day, it's just a name that stands for a single or multiple privileges/abilities for a user to do thing.  In this example, anything within our Custom App involving the borrowing of books should refer to this setting.



Assigning Custom Permissions to Permission Sets

  1. Navigate to Setup --> Administer --> Manage Users --> Permission Sets



  2. Click on the "New" button, provide the required details about your permission set, and then click on the "Save" button.



  3. Within the "Apps" section, click on the "Permission Sets" link



  4. Select the appropriate permissions and then click on the "Save" button



Assigning Permission Sets to Users

  1. Navigate to Setup --> Administer --> Manage Users --> Users


  2. Click on the name of a User


  3. Within the User's Related Lists, hover over "Permission Set Assignments" and click on the "Edit Assignments" button


  4. To apply a Permission Set and its related Custom Permissions, move the Permission Set from the "Available Permission Sets" column to the "Enabled Permissions Sets" column.


Using Customer Permissions

With the creation and assignment out of the way, let's look at how we can use them to control Visualforce UI elements based on their assignment.  

Global Variable Way

Directly from Visualforce, it's as easy as...

Here's an example from the full VF page:


sObject/SOQL Way

We need to access several objects.  First we'll need to query for all CustomPermissions.  Then we'll query for SetupEntityAccess records that apply to the current user based on PermissionSetAssignments - see snippet below.  In the full sample, I've set up a set<string> called LibraryPermissions that will contain the DeveloperNames of CustomPermissions applied to the current user.  I'll also create a method to return string.valueOf(LibraryPermissions) so the Visualforce page can just use CONTAINS(LibaryPermissionsStr, 'the permission I want to check').

Apex Snippet (full code at bottom)


VF Usage



Practical Usage

Showing the permissions is one thing, but using Custom Permissions in a practical way that helps you control UI elements is another.  Using either technique, we can show/hide buttons that apply to that user according to the Permission Sets applied.

Here's a quick snippet of  rendering commandButtons accordingly:


Recap

So there we go!  We've effectively modified a UI by leveraging the semi-new Custom Permissions and demonstrated how they can be created, applied to a User through the use of Permissions Sets.  While showing/hiding buttons isn't too glorious of an example, we'd love to hear how you use them in the comments or on Twitter @crmscience!